mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 22:36:39 +02:00
commit
11e6982a9d
3 changed files with 49 additions and 25 deletions
|
@ -24,7 +24,7 @@ VoxelSendThread::VoxelSendThread(const QUuid& nodeUUID, VoxelServer* myServer) :
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VoxelSendThread::process() {
|
bool VoxelSendThread::process() {
|
||||||
uint64_t lastSendTime = usecTimestampNow();
|
uint64_t start = usecTimestampNow();
|
||||||
|
|
||||||
Node* node = NodeList::getInstance()->nodeWithUUID(_nodeUUID);
|
Node* node = NodeList::getInstance()->nodeWithUUID(_nodeUUID);
|
||||||
VoxelNodeData* nodeData = NULL;
|
VoxelNodeData* nodeData = NULL;
|
||||||
|
@ -32,6 +32,8 @@ bool VoxelSendThread::process() {
|
||||||
if (node) {
|
if (node) {
|
||||||
nodeData = (VoxelNodeData*) node->getLinkedData();
|
nodeData = (VoxelNodeData*) node->getLinkedData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int packetsSent = 0;
|
||||||
|
|
||||||
// Sometimes the node data has not yet been linked, in which case we can't really do anything
|
// Sometimes the node data has not yet been linked, in which case we can't really do anything
|
||||||
if (nodeData) {
|
if (nodeData) {
|
||||||
|
@ -39,11 +41,12 @@ bool VoxelSendThread::process() {
|
||||||
if (_myServer->wantsDebugVoxelSending()) {
|
if (_myServer->wantsDebugVoxelSending()) {
|
||||||
printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged));
|
printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged));
|
||||||
}
|
}
|
||||||
deepestLevelVoxelDistributor(node, nodeData, viewFrustumChanged);
|
packetsSent = deepestLevelVoxelDistributor(node, nodeData, viewFrustumChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
// dynamically sleep until we need to fire off the next set of voxels
|
// dynamically sleep until we need to fire off the next set of voxels
|
||||||
int usecToSleep = VOXEL_SEND_INTERVAL_USECS - (usecTimestampNow() - lastSendTime);
|
int elapsed = (usecTimestampNow() - start);
|
||||||
|
int usecToSleep = VOXEL_SEND_INTERVAL_USECS - elapsed;
|
||||||
|
|
||||||
if (usecToSleep > 0) {
|
if (usecToSleep > 0) {
|
||||||
usleep(usecToSleep);
|
usleep(usecToSleep);
|
||||||
|
@ -52,19 +55,19 @@ bool VoxelSendThread::process() {
|
||||||
std::cout << "Last send took too much time, not sleeping!\n";
|
std::cout << "Last send took too much time, not sleeping!\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return isStillRunning(); // keep running till they terminate us
|
return isStillRunning(); // keep running till they terminate us
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int& trueBytesSent, int& truePacketsSent) {
|
int VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int& trueBytesSent, int& truePacketsSent) {
|
||||||
|
|
||||||
|
int packetsSent = 0;
|
||||||
// Here's where we check to see if this packet is a duplicate of the last packet. If it is, we will silently
|
// Here's where we check to see if this packet is a duplicate of the last packet. If it is, we will silently
|
||||||
// obscure the packet and not send it. This allows the callers and upper level logic to not need to know about
|
// obscure the packet and not send it. This allows the callers and upper level logic to not need to know about
|
||||||
// this rate control savings.
|
// this rate control savings.
|
||||||
if (nodeData->shouldSuppressDuplicatePacket()) {
|
if (nodeData->shouldSuppressDuplicatePacket()) {
|
||||||
nodeData->resetVoxelPacket(); // we still need to reset it though!
|
nodeData->resetVoxelPacket(); // we still need to reset it though!
|
||||||
return; // without sending...
|
return packetsSent; // without sending...
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we've got a stats message ready to send, then see if we can piggyback them together
|
// If we've got a stats message ready to send, then see if we can piggyback them together
|
||||||
|
@ -85,6 +88,10 @@ void VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int&
|
||||||
} else {
|
} else {
|
||||||
// not enough room in the packet, send two packets
|
// not enough room in the packet, send two packets
|
||||||
NodeList::getInstance()->getNodeSocket()->send(node->getActiveSocket(), statsMessage, statsMessageLength);
|
NodeList::getInstance()->getNodeSocket()->send(node->getActiveSocket(), statsMessage, statsMessageLength);
|
||||||
|
trueBytesSent += statsMessageLength;
|
||||||
|
truePacketsSent++;
|
||||||
|
packetsSent++;
|
||||||
|
|
||||||
NodeList::getInstance()->getNodeSocket()->send(node->getActiveSocket(),
|
NodeList::getInstance()->getNodeSocket()->send(node->getActiveSocket(),
|
||||||
nodeData->getPacket(), nodeData->getPacketLength());
|
nodeData->getPacket(), nodeData->getPacketLength());
|
||||||
}
|
}
|
||||||
|
@ -97,16 +104,21 @@ void VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int&
|
||||||
nodeData->stats.packetSent(nodeData->getPacketLength());
|
nodeData->stats.packetSent(nodeData->getPacketLength());
|
||||||
trueBytesSent += nodeData->getPacketLength();
|
trueBytesSent += nodeData->getPacketLength();
|
||||||
truePacketsSent++;
|
truePacketsSent++;
|
||||||
|
packetsSent++;
|
||||||
nodeData->resetVoxelPacket();
|
nodeData->resetVoxelPacket();
|
||||||
|
return packetsSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Version of voxel distributor that sends the deepest LOD level at once
|
/// Version of voxel distributor that sends the deepest LOD level at once
|
||||||
void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nodeData, bool viewFrustumChanged) {
|
int VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nodeData, bool viewFrustumChanged) {
|
||||||
|
|
||||||
_myServer->lockTree();
|
_myServer->lockTree();
|
||||||
|
|
||||||
int truePacketsSent = 0;
|
int truePacketsSent = 0;
|
||||||
int trueBytesSent = 0;
|
int trueBytesSent = 0;
|
||||||
|
int packetsSentThisInterval = 0;
|
||||||
|
bool somethingToSend = true; // assume we have something
|
||||||
|
|
||||||
|
|
||||||
// FOR NOW... node tells us if it wants to receive only view frustum deltas
|
// FOR NOW... node tells us if it wants to receive only view frustum deltas
|
||||||
bool wantDelta = viewFrustumChanged && nodeData->getWantDelta();
|
bool wantDelta = viewFrustumChanged && nodeData->getWantDelta();
|
||||||
|
@ -127,8 +139,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
||||||
debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor()));
|
debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor()));
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (_myServer->wantsDebugVoxelSending()) {
|
if (_myServer->wantsDebugVoxelSending()) {
|
||||||
printf("wantColor=%s --- FIXING HEADER! nodeData->getCurrentPacketIsColor()=%s\n",
|
printf("wantColor=%s --- FIXING HEADER! nodeData->getCurrentPacketIsColor()=%s\n",
|
||||||
|
@ -217,21 +228,26 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
||||||
// If we have something in our nodeBag, then turn them into packets and send them out...
|
// If we have something in our nodeBag, then turn them into packets and send them out...
|
||||||
if (!nodeData->nodeBag.isEmpty()) {
|
if (!nodeData->nodeBag.isEmpty()) {
|
||||||
int bytesWritten = 0;
|
int bytesWritten = 0;
|
||||||
int packetsSentThisInterval = 0;
|
|
||||||
uint64_t start = usecTimestampNow();
|
uint64_t start = usecTimestampNow();
|
||||||
|
|
||||||
bool shouldSendEnvironments = _myServer->wantSendEnvironments() && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS);
|
bool shouldSendEnvironments = _myServer->wantSendEnvironments() && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS);
|
||||||
|
|
||||||
int clientMaxPacketsPerInterval = nodeData->getMaxVoxelPacketsPerSecond() / INTERVALS_PER_SECOND;
|
int clientMaxPacketsPerInterval = std::max(1,(nodeData->getMaxVoxelPacketsPerSecond() / INTERVALS_PER_SECOND));
|
||||||
int maxPacketsPerInterval = std::max(clientMaxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval());
|
int maxPacketsPerInterval = std::min(clientMaxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval());
|
||||||
|
|
||||||
if (_myServer->wantsDebugVoxelSending()) {
|
if (_myServer->wantsDebugVoxelSending()) {
|
||||||
printf("packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n",
|
printf("truePacketsSent=%d packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n",
|
||||||
packetsSentThisInterval, maxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval(),
|
truePacketsSent, packetsSentThisInterval, maxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval(),
|
||||||
nodeData->getMaxVoxelPacketsPerSecond(), clientMaxPacketsPerInterval);
|
nodeData->getMaxVoxelPacketsPerSecond(), clientMaxPacketsPerInterval);
|
||||||
}
|
}
|
||||||
|
while (somethingToSend && packetsSentThisInterval < maxPacketsPerInterval - (shouldSendEnvironments ? 1 : 0)) {
|
||||||
|
if (_myServer->wantsDebugVoxelSending()) {
|
||||||
|
printf("truePacketsSent=%d packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n",
|
||||||
|
truePacketsSent, packetsSentThisInterval, maxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval(),
|
||||||
|
nodeData->getMaxVoxelPacketsPerSecond(), clientMaxPacketsPerInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
while (packetsSentThisInterval < maxPacketsPerInterval - (shouldSendEnvironments ? 1 : 0)) {
|
|
||||||
// Check to see if we're taking too long, and if so bail early...
|
// Check to see if we're taking too long, and if so bail early...
|
||||||
uint64_t now = usecTimestampNow();
|
uint64_t now = usecTimestampNow();
|
||||||
long elapsedUsec = (now - start);
|
long elapsedUsec = (now - start);
|
||||||
|
@ -276,17 +292,18 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
||||||
if (nodeData->getAvailable() >= bytesWritten) {
|
if (nodeData->getAvailable() >= bytesWritten) {
|
||||||
nodeData->writeToPacket(_tempOutputBuffer, bytesWritten);
|
nodeData->writeToPacket(_tempOutputBuffer, bytesWritten);
|
||||||
} else {
|
} else {
|
||||||
handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||||
packetsSentThisInterval++;
|
|
||||||
nodeData->writeToPacket(_tempOutputBuffer, bytesWritten);
|
nodeData->writeToPacket(_tempOutputBuffer, bytesWritten);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (nodeData->isPacketWaiting()) {
|
if (nodeData->isPacketWaiting()) {
|
||||||
handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||||
}
|
}
|
||||||
packetsSentThisInterval = _myServer->getPacketsPerClientPerInterval(); // done for now, no nodes left
|
//packetsSentThisInterval = _myServer->getPacketsPerClientPerInterval(); // done for now, no nodes left
|
||||||
|
somethingToSend = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send the environment packet
|
// send the environment packet
|
||||||
if (shouldSendEnvironments) {
|
if (shouldSendEnvironments) {
|
||||||
int numBytesPacketHeader = populateTypeAndVersion(_tempOutputBuffer, PACKET_TYPE_ENVIRONMENT_DATA);
|
int numBytesPacketHeader = populateTypeAndVersion(_tempOutputBuffer, PACKET_TYPE_ENVIRONMENT_DATA);
|
||||||
|
@ -300,6 +317,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
||||||
NodeList::getInstance()->getNodeSocket()->send(node->getActiveSocket(), _tempOutputBuffer, envPacketLength);
|
NodeList::getInstance()->getNodeSocket()->send(node->getActiveSocket(), _tempOutputBuffer, envPacketLength);
|
||||||
trueBytesSent += envPacketLength;
|
trueBytesSent += envPacketLength;
|
||||||
truePacketsSent++;
|
truePacketsSent++;
|
||||||
|
packetsSentThisInterval++;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t end = usecTimestampNow();
|
uint64_t end = usecTimestampNow();
|
||||||
|
@ -328,9 +346,17 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
||||||
}
|
}
|
||||||
nodeData->map.erase(); // It would be nice if we could save this, and only reset it when the view frustum changes
|
nodeData->map.erase(); // It would be nice if we could save this, and only reset it when the view frustum changes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_myServer->wantsDebugVoxelSending()) {
|
||||||
|
printf("truePacketsSent=%d packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n",
|
||||||
|
truePacketsSent, packetsSentThisInterval, maxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval(),
|
||||||
|
nodeData->getMaxVoxelPacketsPerSecond(), clientMaxPacketsPerInterval);
|
||||||
|
}
|
||||||
|
|
||||||
} // end if bag wasn't empty, and so we sent stuff...
|
} // end if bag wasn't empty, and so we sent stuff...
|
||||||
|
|
||||||
_myServer->unlockTree();
|
_myServer->unlockTree();
|
||||||
|
|
||||||
|
return truePacketsSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,8 @@ private:
|
||||||
QUuid _nodeUUID;
|
QUuid _nodeUUID;
|
||||||
VoxelServer* _myServer;
|
VoxelServer* _myServer;
|
||||||
|
|
||||||
void handlePacketSend(Node* node, VoxelNodeData* nodeData, int& trueBytesSent, int& truePacketsSent);
|
int handlePacketSend(Node* node, VoxelNodeData* nodeData, int& trueBytesSent, int& truePacketsSent);
|
||||||
void deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nodeData, bool viewFrustumChanged);
|
int deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nodeData, bool viewFrustumChanged);
|
||||||
|
|
||||||
unsigned char _tempOutputBuffer[MAX_VOXEL_PACKET_SIZE];
|
unsigned char _tempOutputBuffer[MAX_VOXEL_PACKET_SIZE];
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,11 +18,9 @@
|
||||||
|
|
||||||
|
|
||||||
const int MAX_FILENAME_LENGTH = 1024;
|
const int MAX_FILENAME_LENGTH = 1024;
|
||||||
const int VOXEL_SIZE_BYTES = 3 + (3 * sizeof(float));
|
const int INTERVALS_PER_SECOND = 60;
|
||||||
const int VOXELS_PER_PACKET = (MAX_PACKET_SIZE - 1) / VOXEL_SIZE_BYTES;
|
const int VOXEL_SEND_INTERVAL_USECS = (1000 * 1000)/INTERVALS_PER_SECOND;
|
||||||
const int VOXEL_SEND_INTERVAL_USECS = 17 * 1000; // approximately 60fps
|
|
||||||
const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels
|
const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels
|
||||||
const int INTERVALS_PER_SECOND = 1000 * 1000 / VOXEL_SEND_INTERVAL_USECS;
|
|
||||||
const int ENVIRONMENT_SEND_INTERVAL_USECS = 1000000;
|
const int ENVIRONMENT_SEND_INTERVAL_USECS = 1000000;
|
||||||
|
|
||||||
extern const char* LOCAL_VOXELS_PERSIST_FILE;
|
extern const char* LOCAL_VOXELS_PERSIST_FILE;
|
||||||
|
|
Loading…
Reference in a new issue