mirror of
https://github.com/overte-org/overte.git
synced 2025-07-23 00:34:22 +02:00
Basic editing with delta streaming up and running.
This commit is contained in:
parent
62e8cbedbd
commit
d5695395c4
10 changed files with 118 additions and 68 deletions
|
@ -24,6 +24,10 @@ MetavoxelServer::MetavoxelServer(const unsigned char* dataBuffer, int numBytes)
|
|||
connect(&_sendTimer, SIGNAL(timeout()), SLOT(sendDeltas()));
|
||||
}
|
||||
|
||||
void MetavoxelServer::applyEdit(const MetavoxelEditMessage& edit) {
|
||||
edit.apply(_data);
|
||||
}
|
||||
|
||||
void MetavoxelServer::removeSession(const QUuid& sessionId) {
|
||||
delete _sessions.take(sessionId);
|
||||
}
|
||||
|
@ -74,16 +78,18 @@ void MetavoxelServer::processData(const QByteArray& data, const HifiSockAddr& se
|
|||
// forward to session, creating if necessary
|
||||
MetavoxelSession*& session = _sessions[sessionID];
|
||||
if (!session) {
|
||||
session = new MetavoxelSession(this, sessionID, QByteArray::fromRawData(data.constData(), headerPlusIDSize));
|
||||
session = new MetavoxelSession(this, sessionID, QByteArray::fromRawData(data.constData(), headerPlusIDSize), sender);
|
||||
}
|
||||
session->receivedData(data, sender);
|
||||
}
|
||||
|
||||
MetavoxelSession::MetavoxelSession(MetavoxelServer* server, const QUuid& sessionId, const QByteArray& datagramHeader) :
|
||||
MetavoxelSession::MetavoxelSession(MetavoxelServer* server, const QUuid& sessionId,
|
||||
const QByteArray& datagramHeader, const HifiSockAddr& sender) :
|
||||
QObject(server),
|
||||
_server(server),
|
||||
_sessionId(sessionId),
|
||||
_sequencer(datagramHeader) {
|
||||
_sequencer(datagramHeader),
|
||||
_sender(sender) {
|
||||
|
||||
const int TIMEOUT_INTERVAL = 30 * 1000;
|
||||
_timeoutTimer.setInterval(TIMEOUT_INTERVAL);
|
||||
|
@ -98,6 +104,8 @@ MetavoxelSession::MetavoxelSession(MetavoxelServer* server, const QUuid& session
|
|||
// insert the baseline send record
|
||||
SendRecord record = { 0 };
|
||||
_sendRecords.append(record);
|
||||
|
||||
qDebug() << "Opened session [sessionId=" << _sessionId << ", sender=" << _sender << "]";
|
||||
}
|
||||
|
||||
void MetavoxelSession::receivedData(const QByteArray& data, const HifiSockAddr& sender) {
|
||||
|
@ -114,7 +122,7 @@ void MetavoxelSession::receivedData(const QByteArray& data, const HifiSockAddr&
|
|||
void MetavoxelSession::sendDelta() {
|
||||
Bitstream& out = _sequencer.startPacket();
|
||||
out << QVariant::fromValue(MetavoxelDeltaMessage());
|
||||
//writeDelta(_server->getData(), _sendRecords.first().data, out);
|
||||
_server->getData().writeDelta(_sendRecords.first().data, out);
|
||||
_sequencer.endPacket();
|
||||
|
||||
// record the send
|
||||
|
@ -143,13 +151,16 @@ void MetavoxelSession::clearSendRecordsBefore(int index) {
|
|||
|
||||
void MetavoxelSession::handleMessage(const QVariant& message) {
|
||||
int userType = message.userType();
|
||||
if (userType == ClientStateMessage::Type) {
|
||||
if (userType == CloseSessionMessage::Type) {
|
||||
qDebug() << "Session closed [sessionId=" << _sessionId << ", sender=" << _sender << "]";
|
||||
_server->removeSession(_sessionId);
|
||||
|
||||
} else if (userType == ClientStateMessage::Type) {
|
||||
ClientStateMessage state = message.value<ClientStateMessage>();
|
||||
_position = state.position;
|
||||
|
||||
} else if (userType == MetavoxelEdit::Type) {
|
||||
MetavoxelEdit edit = message.value<MetavoxelEdit>();
|
||||
qDebug() << "got edit " << edit.granularity;
|
||||
} else if (userType == MetavoxelEditMessage::Type) {
|
||||
_server->applyEdit(message.value<MetavoxelEditMessage>());
|
||||
|
||||
} else if (userType == QMetaType::QVariantList) {
|
||||
foreach (const QVariant& element, message.toList()) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <DatagramSequencer.h>
|
||||
#include <MetavoxelData.h>
|
||||
|
||||
class MetavoxelEditMessage;
|
||||
class MetavoxelSession;
|
||||
|
||||
/// Maintains a shared metavoxel system, accepting change requests and broadcasting updates.
|
||||
|
@ -30,6 +31,8 @@ public:
|
|||
|
||||
MetavoxelServer(const unsigned char* dataBuffer, int numBytes);
|
||||
|
||||
void applyEdit(const MetavoxelEditMessage& edit);
|
||||
|
||||
const MetavoxelData& getData() const { return _data; }
|
||||
|
||||
void removeSession(const QUuid& sessionId);
|
||||
|
@ -60,7 +63,8 @@ class MetavoxelSession : public QObject {
|
|||
|
||||
public:
|
||||
|
||||
MetavoxelSession(MetavoxelServer* server, const QUuid& sessionId, const QByteArray& datagramHeader);
|
||||
MetavoxelSession(MetavoxelServer* server, const QUuid& sessionId,
|
||||
const QByteArray& datagramHeader, const HifiSockAddr& sender);
|
||||
|
||||
void receivedData(const QByteArray& data, const HifiSockAddr& sender);
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ void MetavoxelSystem::init() {
|
|||
_buffer.create();
|
||||
}
|
||||
|
||||
void MetavoxelSystem::applyEdit(const MetavoxelEdit& edit) {
|
||||
void MetavoxelSystem::applyEdit(const MetavoxelEditMessage& edit) {
|
||||
foreach (MetavoxelClient* client, _clients) {
|
||||
client->applyEdit(edit);
|
||||
}
|
||||
|
@ -190,7 +190,14 @@ MetavoxelClient::MetavoxelClient(const HifiSockAddr& address) :
|
|||
_receiveRecords.append(record);
|
||||
}
|
||||
|
||||
void MetavoxelClient::applyEdit(const MetavoxelEdit& edit) {
|
||||
MetavoxelClient::~MetavoxelClient() {
|
||||
// close the session
|
||||
Bitstream& out = _sequencer.startPacket();
|
||||
out << QVariant::fromValue(CloseSessionMessage());
|
||||
_sequencer.endPacket();
|
||||
}
|
||||
|
||||
void MetavoxelClient::applyEdit(const MetavoxelEditMessage& edit) {
|
||||
// apply immediately to local tree
|
||||
edit.apply(_data);
|
||||
|
||||
|
@ -227,6 +234,13 @@ void MetavoxelClient::readPacket(Bitstream& in) {
|
|||
// record the receipt
|
||||
ReceiveRecord record = { _sequencer.getIncomingPacketNumber(), _data };
|
||||
_receiveRecords.append(record);
|
||||
|
||||
// reapply local edits
|
||||
foreach (const DatagramSequencer::HighPriorityMessage& message, _sequencer.getHighPriorityMessages()) {
|
||||
if (message.data.userType() == MetavoxelEditMessage::Type) {
|
||||
message.data.value<MetavoxelEditMessage>().apply(_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MetavoxelClient::clearReceiveRecordsBefore(int index) {
|
||||
|
@ -236,7 +250,7 @@ void MetavoxelClient::clearReceiveRecordsBefore(int index) {
|
|||
void MetavoxelClient::handleMessage(const QVariant& message, Bitstream& in) {
|
||||
int userType = message.userType();
|
||||
if (userType == MetavoxelDeltaMessage::Type) {
|
||||
// readDelta(_data, _receiveRecords.first().data, in);
|
||||
_data.readDelta(_receiveRecords.first().data, in);
|
||||
|
||||
} else if (userType == QMetaType::QVariantList) {
|
||||
foreach (const QVariant& element, message.toList()) {
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
|
||||
void init();
|
||||
|
||||
void applyEdit(const MetavoxelEdit& edit);
|
||||
void applyEdit(const MetavoxelEditMessage& edit);
|
||||
|
||||
void processData(const QByteArray& data, const HifiSockAddr& sender);
|
||||
|
||||
|
@ -87,10 +87,11 @@ class MetavoxelClient : public QObject {
|
|||
public:
|
||||
|
||||
MetavoxelClient(const HifiSockAddr& address);
|
||||
virtual ~MetavoxelClient();
|
||||
|
||||
const QUuid& getSessionID() const { return _sessionID; }
|
||||
|
||||
void applyEdit(const MetavoxelEdit& edit);
|
||||
void applyEdit(const MetavoxelEditMessage& edit);
|
||||
|
||||
void simulate(float deltaTime, MetavoxelVisitor& visitor);
|
||||
|
||||
|
|
|
@ -348,7 +348,7 @@ void MetavoxelEditor::applyValue(const glm::vec3& minimum, const glm::vec3& maxi
|
|||
return;
|
||||
}
|
||||
OwnedAttributeValue value(attribute, attribute->createFromVariant(getValue()));
|
||||
MetavoxelEdit edit = { minimum, maximum, getGridSpacing(), value };
|
||||
MetavoxelEditMessage edit = { minimum, maximum, getGridSpacing(), value };
|
||||
Application::getInstance()->getMetavoxels()->applyEdit(edit);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,12 @@ class DatagramSequencer : public QObject {
|
|||
|
||||
public:
|
||||
|
||||
class HighPriorityMessage {
|
||||
public:
|
||||
QVariant data;
|
||||
int firstPacketNumber;
|
||||
};
|
||||
|
||||
DatagramSequencer(const QByteArray& datagramHeader = QByteArray());
|
||||
|
||||
/// Returns the packet number of the last packet sent.
|
||||
|
@ -37,6 +43,9 @@ public:
|
|||
/// Adds a message to the high priority queue. Will be sent with every outgoing packet until received.
|
||||
void sendHighPriorityMessage(const QVariant& data);
|
||||
|
||||
/// Returns a reference to the list of high priority messages not yet acknowledged.
|
||||
const QList<HighPriorityMessage>& getHighPriorityMessages() const { return _highPriorityMessages; }
|
||||
|
||||
/// Starts a new packet for transmission.
|
||||
/// \return a reference to the Bitstream to use for writing to the packet
|
||||
Bitstream& startPacket();
|
||||
|
@ -85,12 +94,6 @@ private:
|
|||
bool operator<(const ReceiveRecord& other) const { return packetNumber < other.packetNumber; }
|
||||
};
|
||||
|
||||
class HighPriorityMessage {
|
||||
public:
|
||||
QVariant data;
|
||||
int firstPacketNumber;
|
||||
};
|
||||
|
||||
/// Notes that the described send was acknowledged by the other party.
|
||||
void sendRecordAcknowledged(const SendRecord& record);
|
||||
|
||||
|
|
|
@ -72,28 +72,20 @@ void MetavoxelData::guide(MetavoxelVisitor& visitor) {
|
|||
}
|
||||
|
||||
void MetavoxelData::read(Bitstream& in) {
|
||||
// save the old roots and clear
|
||||
QHash<AttributePointer, MetavoxelNode*> oldRoots = _roots;
|
||||
// clear out any existing roots
|
||||
decrementRootReferenceCounts();
|
||||
_roots.clear();
|
||||
|
||||
// read in the new roots, reusing old ones where appropriate
|
||||
|
||||
// read in the new roots
|
||||
int rootCount;
|
||||
in >> rootCount;
|
||||
for (int i = 0; i < rootCount; i++) {
|
||||
AttributePointer attribute;
|
||||
in.getAttributeStreamer() >> attribute;
|
||||
MetavoxelNode* root = oldRoots.take(attribute);
|
||||
if (!root) {
|
||||
root = new MetavoxelNode(attribute);
|
||||
}
|
||||
_roots.insert(attribute, root);
|
||||
MetavoxelNode*& root = _roots[attribute];
|
||||
root = new MetavoxelNode(attribute);
|
||||
root->read(attribute, in);
|
||||
}
|
||||
|
||||
// clear out the remaining old roots
|
||||
for (QHash<AttributePointer, MetavoxelNode*>::const_iterator it = oldRoots.constBegin(); it != oldRoots.constEnd(); it++) {
|
||||
it.value()->decrementReferenceCount(it.key());
|
||||
}
|
||||
}
|
||||
|
||||
void MetavoxelData::write(Bitstream& out) const {
|
||||
|
@ -105,22 +97,25 @@ void MetavoxelData::write(Bitstream& out) const {
|
|||
}
|
||||
|
||||
void MetavoxelData::readDelta(const MetavoxelData& reference, Bitstream& in) {
|
||||
// shallow copy the reference
|
||||
*this = reference;
|
||||
|
||||
int changedCount;
|
||||
in >> changedCount;
|
||||
for (int i = 0; i < changedCount; i++) {
|
||||
AttributePointer attribute;
|
||||
in.getAttributeStreamer() >> attribute;
|
||||
MetavoxelNode*& root = _roots[attribute];
|
||||
if (!root) {
|
||||
if (root) {
|
||||
MetavoxelNode* oldRoot = root;
|
||||
root = new MetavoxelNode(attribute);
|
||||
}
|
||||
MetavoxelNode* referenceRoot = reference._roots.value(attribute);
|
||||
if (referenceRoot) {
|
||||
root->readDelta(attribute, *referenceRoot, in);
|
||||
|
||||
root->readDelta(attribute, *oldRoot, in);
|
||||
oldRoot->decrementReferenceCount(attribute);
|
||||
|
||||
} else {
|
||||
root = new MetavoxelNode(attribute);
|
||||
root->read(attribute, in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int removedCount;
|
||||
|
@ -128,7 +123,7 @@ void MetavoxelData::readDelta(const MetavoxelData& reference, Bitstream& in) {
|
|||
for (int i = 0; i < removedCount; i++) {
|
||||
AttributePointer attribute;
|
||||
in.getAttributeStreamer() >> attribute;
|
||||
|
||||
_roots.take(attribute)->decrementReferenceCount(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,22 +226,16 @@ bool MetavoxelNode::isLeaf() const {
|
|||
}
|
||||
|
||||
void MetavoxelNode::read(const AttributePointer& attribute, Bitstream& in) {
|
||||
clearChildren(attribute);
|
||||
|
||||
bool leaf;
|
||||
in >> leaf;
|
||||
attribute->read(in, _attributeValue, leaf);
|
||||
if (leaf) {
|
||||
clearChildren(attribute);
|
||||
|
||||
} else {
|
||||
void* childValues[CHILD_COUNT];
|
||||
if (!leaf) {
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
if (!_children[i]) {
|
||||
_children[i] = new MetavoxelNode(attribute);
|
||||
}
|
||||
_children[i] = new MetavoxelNode(attribute);
|
||||
_children[i]->read(attribute, in);
|
||||
childValues[i] = _children[i]->_attributeValue;
|
||||
}
|
||||
attribute->merge(_attributeValue, childValues);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,20 +251,28 @@ void MetavoxelNode::write(const AttributePointer& attribute, Bitstream& out) con
|
|||
}
|
||||
|
||||
void MetavoxelNode::readDelta(const AttributePointer& attribute, const MetavoxelNode& reference, Bitstream& in) {
|
||||
clearChildren(attribute);
|
||||
|
||||
bool leaf;
|
||||
in >> leaf;
|
||||
attribute->readDelta(in, _attributeValue, reference._attributeValue, leaf);
|
||||
if (leaf) {
|
||||
clearChildren(attribute);
|
||||
|
||||
} else {
|
||||
if (!leaf) {
|
||||
if (reference.isLeaf()) {
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
_children[i] = new MetavoxelNode(attribute);
|
||||
_children[i]->read(attribute, in);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
_children[i]->readDelta(attribute, *reference._children[i], in);
|
||||
bool changed;
|
||||
in >> changed;
|
||||
if (changed) {
|
||||
_children[i] = new MetavoxelNode(attribute);
|
||||
_children[i]->readDelta(attribute, *reference._children[i], in);
|
||||
} else {
|
||||
_children[i] = reference._children[i];
|
||||
_children[i]->incrementReferenceCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -292,7 +289,12 @@ void MetavoxelNode::writeDelta(const AttributePointer& attribute, const Metavoxe
|
|||
}
|
||||
} else {
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
_children[i]->writeDelta(attribute, *reference._children[i], out);
|
||||
if (_children[i] == reference._children[i]) {
|
||||
out << false;
|
||||
} else {
|
||||
out << true;
|
||||
_children[i]->writeDelta(attribute, *reference._children[i], out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -343,9 +345,16 @@ void DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
|||
visitation.info.isLeaf = visitation.allInputNodesLeaves();
|
||||
bool keepGoing = visitation.visitor.visit(visitation.info);
|
||||
for (int i = 0; i < visitation.outputNodes.size(); i++) {
|
||||
const AttributeValue& value = visitation.info.outputValues[i];
|
||||
if (value.getAttribute()) {
|
||||
visitation.outputNodes[i] = new MetavoxelNode(value);
|
||||
AttributeValue& value = visitation.info.outputValues[i];
|
||||
if (!value.getAttribute()) {
|
||||
continue;
|
||||
}
|
||||
MetavoxelNode*& node = visitation.outputNodes[i];
|
||||
if (node && node->isLeaf() && value.getAttribute()->equal(value.getValue(), node->getAttributeValue())) {
|
||||
// "set" to same value; disregard
|
||||
value = AttributeValue();
|
||||
} else {
|
||||
node = new MetavoxelNode(value);
|
||||
}
|
||||
}
|
||||
if (!keepGoing) {
|
||||
|
|
|
@ -67,6 +67,7 @@ public:
|
|||
void setAttributeValue(const AttributeValue& attributeValue);
|
||||
|
||||
AttributeValue getAttributeValue(const AttributePointer& attribute) const;
|
||||
void* getAttributeValue() const { return _attributeValue; }
|
||||
|
||||
void mergeChildren(const AttributePointer& attribute);
|
||||
|
||||
|
|
|
@ -12,16 +12,16 @@
|
|||
class EditVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
EditVisitor(const MetavoxelEdit& edit);
|
||||
EditVisitor(const MetavoxelEditMessage& edit);
|
||||
|
||||
virtual bool visit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
const MetavoxelEdit& _edit;
|
||||
const MetavoxelEditMessage& _edit;
|
||||
};
|
||||
|
||||
EditVisitor::EditVisitor(const MetavoxelEdit& edit) :
|
||||
EditVisitor::EditVisitor(const MetavoxelEditMessage& edit) :
|
||||
MetavoxelVisitor(QVector<AttributePointer>(), QVector<AttributePointer>() << edit.value.getAttribute()),
|
||||
_edit(edit) {
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ bool EditVisitor::visit(MetavoxelInfo& info) {
|
|||
return true; // subdivide
|
||||
}
|
||||
|
||||
void MetavoxelEdit::apply(MetavoxelData& data) const {
|
||||
void MetavoxelEditMessage::apply(MetavoxelData& data) const {
|
||||
EditVisitor visitor(*this);
|
||||
data.guide(visitor);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,13 @@
|
|||
|
||||
class MetavoxelData;
|
||||
|
||||
/// Requests to close the session.
|
||||
class CloseSessionMessage {
|
||||
STREAMABLE
|
||||
};
|
||||
|
||||
DECLARE_STREAMABLE_METATYPE(CloseSessionMessage)
|
||||
|
||||
/// A message containing the state of a client.
|
||||
class ClientStateMessage {
|
||||
STREAMABLE
|
||||
|
@ -33,7 +40,7 @@ class MetavoxelDeltaMessage {
|
|||
DECLARE_STREAMABLE_METATYPE(MetavoxelDeltaMessage)
|
||||
|
||||
/// A simple streamable edit.
|
||||
class MetavoxelEdit {
|
||||
class MetavoxelEditMessage {
|
||||
STREAMABLE
|
||||
|
||||
public:
|
||||
|
@ -46,6 +53,6 @@ public:
|
|||
void apply(MetavoxelData& data) const;
|
||||
};
|
||||
|
||||
DECLARE_STREAMABLE_METATYPE(MetavoxelEdit)
|
||||
DECLARE_STREAMABLE_METATYPE(MetavoxelEditMessage)
|
||||
|
||||
#endif /* defined(__interface__MetavoxelMessages__) */
|
||||
|
|
Loading…
Reference in a new issue