mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 16:13:28 +02:00
Working on metavoxel streaming tests.
This commit is contained in:
parent
7a9c0f0e6a
commit
24f535e02d
3 changed files with 196 additions and 54 deletions
|
@ -687,6 +687,23 @@ MetavoxelNode* MetavoxelData::createRoot(const AttributePointer& attribute) {
|
|||
return root = new MetavoxelNode(attribute);
|
||||
}
|
||||
|
||||
bool MetavoxelData::deepEquals(const MetavoxelData& other, const MetavoxelLOD& lod) const {
|
||||
if (_size != other._size) {
|
||||
return false;
|
||||
}
|
||||
if (_roots.size() != other._roots.size()) {
|
||||
return false;
|
||||
}
|
||||
glm::vec3 minimum = getMinimum();
|
||||
for (QHash<AttributePointer, MetavoxelNode*>::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) {
|
||||
MetavoxelNode* otherNode = other._roots.value(it.key());
|
||||
if (!(otherNode && it.value()->deepEquals(it.key(), *otherNode, minimum, _size, lod))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MetavoxelData::operator==(const MetavoxelData& other) const {
|
||||
return _size == other._size && _roots == other._roots;
|
||||
}
|
||||
|
@ -1083,6 +1100,31 @@ void MetavoxelNode::clearChildren(const AttributePointer& attribute) {
|
|||
}
|
||||
}
|
||||
|
||||
bool MetavoxelNode::deepEquals(const AttributePointer& attribute, const MetavoxelNode& other,
|
||||
const glm::vec3& minimum, float size, const MetavoxelLOD& lod) const {
|
||||
if (!attribute->equal(_attributeValue, other._attributeValue)) {
|
||||
return false;
|
||||
}
|
||||
if (!lod.shouldSubdivide(minimum, size, attribute->getLODThresholdMultiplier())) {
|
||||
return true;
|
||||
}
|
||||
bool leaf = isLeaf(), otherLeaf = other.isLeaf();
|
||||
if (leaf && otherLeaf) {
|
||||
return true;
|
||||
}
|
||||
if (leaf || otherLeaf) {
|
||||
return false;
|
||||
}
|
||||
float nextSize = size * 0.5f;
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
glm::vec3 nextMinimum = getNextMinimum(minimum, nextSize, i);
|
||||
if (!_children[i]->deepEquals(attribute, *(other._children[i]), nextMinimum, nextSize, lod)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int MetavoxelVisitor::encodeOrder(int first, int second, int third, int fourth,
|
||||
int fifth, int sixth, int seventh, int eighth) {
|
||||
return first | (second << 3) | (third << 6) | (fourth << 9) |
|
||||
|
@ -1111,6 +1153,10 @@ int MetavoxelVisitor::encodeOrder(const glm::vec3& direction) {
|
|||
indexDistances.at(6).index, indexDistances.at(7).index);
|
||||
}
|
||||
|
||||
int MetavoxelVisitor::encodeRandomOrder() {
|
||||
return DEFAULT_ORDER;
|
||||
}
|
||||
|
||||
const int MetavoxelVisitor::DEFAULT_ORDER = encodeOrder(0, 1, 2, 3, 4, 5, 6, 7);
|
||||
const int MetavoxelVisitor::STOP_RECURSION = 0;
|
||||
const int MetavoxelVisitor::SHORT_CIRCUIT = -1;
|
||||
|
|
|
@ -126,6 +126,10 @@ public:
|
|||
MetavoxelNode* getRoot(const AttributePointer& attribute) const { return _roots.value(attribute); }
|
||||
MetavoxelNode* createRoot(const AttributePointer& attribute);
|
||||
|
||||
/// Performs a deep comparison between this data and the specified other (as opposed to the == operator, which does a
|
||||
/// shallow comparison).
|
||||
bool deepEquals(const MetavoxelData& other, const MetavoxelLOD& lod = MetavoxelLOD()) const;
|
||||
|
||||
bool operator==(const MetavoxelData& other) const;
|
||||
bool operator!=(const MetavoxelData& other) const;
|
||||
|
||||
|
@ -214,6 +218,10 @@ public:
|
|||
|
||||
void clearChildren(const AttributePointer& attribute);
|
||||
|
||||
/// Performs a deep comparison between this and the specified other node.
|
||||
bool deepEquals(const AttributePointer& attribute, const MetavoxelNode& other,
|
||||
const glm::vec3& minimum, float size, const MetavoxelLOD& lod) const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(MetavoxelNode)
|
||||
|
||||
|
@ -250,6 +258,9 @@ public:
|
|||
/// Encodes a visitation order sequence that visits each child as sorted along the specified direction.
|
||||
static int encodeOrder(const glm::vec3& direction);
|
||||
|
||||
/// Returns a random visitation order sequence.
|
||||
static int encodeRandomOrder();
|
||||
|
||||
/// The default visitation order.
|
||||
static const int DEFAULT_ORDER;
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ static int datagramsSent = 0;
|
|||
static int datagramsReceived = 0;
|
||||
static int bytesSent = 0;
|
||||
static int bytesReceived = 0;
|
||||
static int maxDatagramsPerPacket = 0;
|
||||
static int maxBytesPerPacket = 0;
|
||||
static int highPriorityMessagesSent = 0;
|
||||
static int highPriorityMessagesReceived = 0;
|
||||
static int unreliableMessagesSent = 0;
|
||||
|
@ -353,6 +355,7 @@ bool MetavoxelTests::run() {
|
|||
qDebug() << "Sent" << streamedBytesSent << "streamed bytes, received" << streamedBytesReceived;
|
||||
qDebug() << "Sent" << datagramsSent << "datagrams with" << bytesSent << "bytes, received" <<
|
||||
datagramsReceived << "with" << bytesReceived << "bytes";
|
||||
qDebug() << "Max" << maxDatagramsPerPacket << "datagrams," << maxBytesPerPacket << "bytes per packet";
|
||||
qDebug() << "Created" << sharedObjectsCreated << "shared objects, destroyed" << sharedObjectsDestroyed;
|
||||
qDebug() << "Performed" << objectMutationsPerformed << "object mutations";
|
||||
qDebug() << "Created" << scriptObjectsCreated << "script objects, mutated" << scriptMutationsPerformed;
|
||||
|
@ -373,7 +376,7 @@ bool MetavoxelTests::run() {
|
|||
qDebug();
|
||||
|
||||
// clear the stats
|
||||
datagramsSent = bytesSent = datagramsReceived = bytesReceived = 0;
|
||||
datagramsSent = bytesSent = datagramsReceived = bytesReceived = maxDatagramsPerPacket = maxBytesPerPacket = 0;
|
||||
|
||||
// create client and server endpoints
|
||||
Endpoint client(datagramHeader, Endpoint::METAVOXEL_CLIENT_MODE);
|
||||
|
@ -391,6 +394,7 @@ bool MetavoxelTests::run() {
|
|||
|
||||
qDebug() << "Sent" << datagramsSent << "datagrams with" << bytesSent << "bytes, received" <<
|
||||
datagramsReceived << "with" << bytesReceived << "bytes";
|
||||
qDebug() << "Max" << maxDatagramsPerPacket << "datagrams," << maxBytesPerPacket << "bytes per packet";
|
||||
}
|
||||
|
||||
qDebug() << "All tests passed!";
|
||||
|
@ -407,6 +411,34 @@ static SharedObjectPointer createRandomSharedObject() {
|
|||
}
|
||||
}
|
||||
|
||||
class RandomVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
int leafCount;
|
||||
|
||||
RandomVisitor();
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
};
|
||||
|
||||
RandomVisitor::RandomVisitor() :
|
||||
MetavoxelVisitor(QVector<AttributePointer>(),
|
||||
QVector<AttributePointer>() << AttributeRegistry::getInstance()->getColorAttribute()),
|
||||
leafCount(0) {
|
||||
}
|
||||
|
||||
const float MAXIMUM_LEAF_SIZE = 0.5f;
|
||||
const float MINIMUM_LEAF_SIZE = 0.25f;
|
||||
|
||||
int RandomVisitor::visit(MetavoxelInfo& info) {
|
||||
if (info.size > MAXIMUM_LEAF_SIZE || (info.size > MINIMUM_LEAF_SIZE && randomBoolean())) {
|
||||
return DEFAULT_ORDER;
|
||||
}
|
||||
info.outputValues[0] = OwnedAttributeValue(_outputs.at(0), encodeInline<QRgb>(qRgb(randIntInRange(0, 255),
|
||||
randIntInRange(0, 255), randIntInRange(0, 255))));
|
||||
leafCount++;
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
||||
Endpoint::Endpoint(const QByteArray& datagramHeader, Mode mode) :
|
||||
_mode(mode),
|
||||
_sequencer(new DatagramSequencer(datagramHeader, this)),
|
||||
|
@ -434,6 +466,12 @@ Endpoint::Endpoint(const QByteArray& datagramHeader, Mode mode) :
|
|||
return;
|
||||
}
|
||||
if (mode == METAVOXEL_SERVER_MODE) {
|
||||
_data.expand();
|
||||
_data.expand();
|
||||
|
||||
RandomVisitor visitor;
|
||||
_data.guide(visitor);
|
||||
qDebug() << "Created" << visitor.leafCount << "base leaves";
|
||||
return;
|
||||
}
|
||||
// create the object that represents out delta-encoded state
|
||||
|
@ -552,6 +590,36 @@ static bool messagesEqual(const QVariant& firstMessage, const QVariant& secondMe
|
|||
}
|
||||
}
|
||||
|
||||
class MutateVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
MutateVisitor();
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
bool _finished;
|
||||
};
|
||||
|
||||
MutateVisitor::MutateVisitor() :
|
||||
MetavoxelVisitor(QVector<AttributePointer>(),
|
||||
QVector<AttributePointer>() << AttributeRegistry::getInstance()->getColorAttribute()),
|
||||
_finished(false) {
|
||||
}
|
||||
|
||||
int MutateVisitor::visit(MetavoxelInfo& info) {
|
||||
if (_finished) {
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
if (info.size > MAXIMUM_LEAF_SIZE || (info.size > MINIMUM_LEAF_SIZE && randomBoolean())) {
|
||||
return encodeRandomOrder();
|
||||
}
|
||||
info.outputValues[0] = OwnedAttributeValue(_outputs.at(0), encodeInline<QRgb>(qRgb(randIntInRange(0, 255),
|
||||
randIntInRange(0, 255), randIntInRange(0, 255))));
|
||||
_finished = true;
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
||||
bool Endpoint::simulate(int iterationNumber) {
|
||||
// update/send our delayed datagrams
|
||||
for (QList<QPair<QByteArray, int> >::iterator it = _delayedDatagrams.begin(); it != _delayedDatagrams.end(); ) {
|
||||
|
@ -565,6 +633,8 @@ bool Endpoint::simulate(int iterationNumber) {
|
|||
}
|
||||
}
|
||||
|
||||
int oldDatagramsSent = datagramsSent;
|
||||
int oldBytesSent = bytesSent;
|
||||
if (_mode == METAVOXEL_CLIENT_MODE) {
|
||||
Bitstream& out = _sequencer->startPacket();
|
||||
|
||||
|
@ -575,69 +645,74 @@ bool Endpoint::simulate(int iterationNumber) {
|
|||
// record the send
|
||||
SendRecord record = { _sequencer->getOutgoingPacketNumber(), SharedObjectPointer(), MetavoxelData(), _lod };
|
||||
_sendRecords.append(record);
|
||||
return false;
|
||||
}
|
||||
if (_mode == METAVOXEL_SERVER_MODE) {
|
||||
// wait until we have a valid lod
|
||||
|
||||
} else if (_mode == METAVOXEL_SERVER_MODE) {
|
||||
// make a random change
|
||||
MutateVisitor visitor;
|
||||
_data.guide(visitor);
|
||||
|
||||
// wait until we have a valid lod before sending
|
||||
if (!_lod.isValid()) {
|
||||
return false;
|
||||
}
|
||||
Bitstream& out = _sequencer->startPacket();
|
||||
out << QVariant::fromValue(MetavoxelDeltaMessage());
|
||||
_data.writeDelta(_sendRecords.first().data, _sendRecords.first().lod, out, _lod);
|
||||
_sequencer->endPacket();
|
||||
|
||||
// record the send
|
||||
SendRecord record = { _sequencer->getOutgoingPacketNumber(), SharedObjectPointer(), _data, _lod };
|
||||
SendRecord record = { _sequencer->getOutgoingPacketNumber() + 1, SharedObjectPointer(), _data, _lod };
|
||||
_sendRecords.append(record);
|
||||
return false;
|
||||
}
|
||||
|
||||
// enqueue some number of high priority messages
|
||||
const float MIN_HIGH_PRIORITY_MESSAGES = 0.0f;
|
||||
const float MAX_HIGH_PRIORITY_MESSAGES = 2.0f;
|
||||
_highPriorityMessagesToSend += randFloatInRange(MIN_HIGH_PRIORITY_MESSAGES, MAX_HIGH_PRIORITY_MESSAGES);
|
||||
while (_highPriorityMessagesToSend >= 1.0f) {
|
||||
QVariant message = createRandomMessage();
|
||||
_highPriorityMessagesSent.append(message);
|
||||
_sequencer->sendHighPriorityMessage(message);
|
||||
highPriorityMessagesSent++;
|
||||
_highPriorityMessagesToSend -= 1.0f;
|
||||
}
|
||||
|
||||
// and some number of reliable messages
|
||||
const float MIN_RELIABLE_MESSAGES = 0.0f;
|
||||
const float MAX_RELIABLE_MESSAGES = 4.0f;
|
||||
_reliableMessagesToSend += randFloatInRange(MIN_RELIABLE_MESSAGES, MAX_RELIABLE_MESSAGES);
|
||||
while (_reliableMessagesToSend >= 1.0f) {
|
||||
QVariant message = createRandomMessage();
|
||||
_reliableMessagesSent.append(message);
|
||||
_sequencer->getReliableOutputChannel()->sendMessage(message);
|
||||
reliableMessagesSent++;
|
||||
_reliableMessagesToSend -= 1.0f;
|
||||
}
|
||||
|
||||
// tweak the local state
|
||||
_localState = mutate(_localState);
|
||||
|
||||
// send a packet
|
||||
try {
|
||||
Bitstream& out = _sequencer->startPacket();
|
||||
SequencedTestMessage message = { iterationNumber, createRandomMessage(), _localState };
|
||||
_unreliableMessagesSent.append(message);
|
||||
unreliableMessagesSent++;
|
||||
out << message;
|
||||
|
||||
_sequencer->endPacket();
|
||||
|
||||
} else {
|
||||
// enqueue some number of high priority messages
|
||||
const float MIN_HIGH_PRIORITY_MESSAGES = 0.0f;
|
||||
const float MAX_HIGH_PRIORITY_MESSAGES = 2.0f;
|
||||
_highPriorityMessagesToSend += randFloatInRange(MIN_HIGH_PRIORITY_MESSAGES, MAX_HIGH_PRIORITY_MESSAGES);
|
||||
while (_highPriorityMessagesToSend >= 1.0f) {
|
||||
QVariant message = createRandomMessage();
|
||||
_highPriorityMessagesSent.append(message);
|
||||
_sequencer->sendHighPriorityMessage(message);
|
||||
highPriorityMessagesSent++;
|
||||
_highPriorityMessagesToSend -= 1.0f;
|
||||
}
|
||||
|
||||
// and some number of reliable messages
|
||||
const float MIN_RELIABLE_MESSAGES = 0.0f;
|
||||
const float MAX_RELIABLE_MESSAGES = 4.0f;
|
||||
_reliableMessagesToSend += randFloatInRange(MIN_RELIABLE_MESSAGES, MAX_RELIABLE_MESSAGES);
|
||||
while (_reliableMessagesToSend >= 1.0f) {
|
||||
QVariant message = createRandomMessage();
|
||||
_reliableMessagesSent.append(message);
|
||||
_sequencer->getReliableOutputChannel()->sendMessage(message);
|
||||
reliableMessagesSent++;
|
||||
_reliableMessagesToSend -= 1.0f;
|
||||
}
|
||||
|
||||
// tweak the local state
|
||||
_localState = mutate(_localState);
|
||||
|
||||
// send a packet
|
||||
try {
|
||||
Bitstream& out = _sequencer->startPacket();
|
||||
SequencedTestMessage message = { iterationNumber, createRandomMessage(), _localState };
|
||||
_unreliableMessagesSent.append(message);
|
||||
unreliableMessagesSent++;
|
||||
out << message;
|
||||
_sequencer->endPacket();
|
||||
|
||||
} catch (const QString& message) {
|
||||
qDebug() << message;
|
||||
return true;
|
||||
}
|
||||
|
||||
} catch (const QString& message) {
|
||||
qDebug() << message;
|
||||
return true;
|
||||
// record the send
|
||||
SendRecord record = { _sequencer->getOutgoingPacketNumber(), _localState };
|
||||
_sendRecords.append(record);
|
||||
}
|
||||
|
||||
// record the send
|
||||
SendRecord record = { _sequencer->getOutgoingPacketNumber(), _localState };
|
||||
_sendRecords.append(record);
|
||||
|
||||
maxDatagramsPerPacket = qMax(maxDatagramsPerPacket, datagramsSent - oldDatagramsSent);
|
||||
maxBytesPerPacket = qMax(maxBytesPerPacket, bytesSent - oldBytesSent);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -692,9 +767,19 @@ void Endpoint::readMessage(Bitstream& in) {
|
|||
in >> message;
|
||||
handleMessage(message, in);
|
||||
|
||||
// deep-compare data to sent version
|
||||
int packetNumber = _sequencer->getIncomingPacketNumber();
|
||||
foreach (const SendRecord& sendRecord, _other->_sendRecords) {
|
||||
if (sendRecord.packetNumber == packetNumber) {
|
||||
if (!sendRecord.data.deepEquals(_data, _sendRecords.first().lod)) {
|
||||
throw QString("Sent/received metavoxel data mismatch.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// record the receipt
|
||||
ReceiveRecord record = { _sequencer->getIncomingPacketNumber(), SharedObjectPointer(),
|
||||
_data, _sendRecords.first().lod };
|
||||
ReceiveRecord record = { packetNumber, SharedObjectPointer(), _data, _sendRecords.first().lod };
|
||||
_receiveRecords.append(record);
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue