From a0ba78867906748b1ae382c9fa3968aa4c17b7f4 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 1 Aug 2013 15:40:39 -0700 Subject: [PATCH] implement grid landscape import --- interface/src/Application.cpp | 180 +++++++++++++++++--------- libraries/voxels/src/VoxelConstants.h | 2 + voxel-server/src/main.cpp | 15 +++ 3 files changed, 136 insertions(+), 61 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f331ee9407..87f52ef285 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1490,16 +1490,18 @@ bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) { uint64_t now = usecTimestampNow(); // dynamically sleep until we need to fire off the next set of voxels - const uint64_t CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS = 1000 * 5; // 1 packet every 10 milliseconds uint64_t elapsed = now - args->lastSendTime; int usecToSleep = CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS - elapsed; if (usecToSleep > 0) { - qDebug("sendVoxelsOperation: packet: %d bytes:%lld elapsed %lld usecs, sleeping for %d usecs!\n", - args->packetsSent, (long long int)args->bytesSent, (long long int)elapsed, usecToSleep); + //qDebug("sendVoxelsOperation: packet: %d bytes:%lld elapsed %lld usecs, sleeping for %d usecs!\n", + // args->packetsSent, (long long int)args->bytesSent, (long long int)elapsed, usecToSleep); + + Application::getInstance()->timer(); + usleep(usecToSleep); } else { - qDebug("sendVoxelsOperation: packet: %d bytes:%lld elapsed %lld usecs, no need to sleep!\n", - args->packetsSent, (long long int)args->bytesSent, (long long int)elapsed); + //qDebug("sendVoxelsOperation: packet: %d bytes:%lld elapsed %lld usecs, no need to sleep!\n", + // args->packetsSent, (long long int)args->bytesSent, (long long int)elapsed); } args->lastSendTime = now; } @@ -1567,70 +1569,127 @@ void Application::importVoxelsToClipboard() { void Application::importVoxels() { QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation); - QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), desktopLocation, + + QStringList fileNameStringList = QFileDialog::getOpenFileNames(_glWidget, tr("Import Voxels"), desktopLocation, tr(IMPORT_FILE_TYPES)); - QByteArray fileNameAscii = fileNameString.toAscii(); - const char* fileName = fileNameAscii.data(); + + // remember the "selected" voxel point before we do any importing... + float originalX = _mouseVoxel.x; + float originalZ = _mouseVoxel.z; + + const int PNG_TYPE_NAME_LENGTH = 4; + const int SVO_TYPE_NAME_LENGTH = 4; + const int SCH_TYPE_NAME_LENGTH = 10; + + for (int i = 0; i < fileNameStringList.size(); i++) { + QString fileNameString = fileNameStringList.at(i); + QByteArray fileNameAscii = fileNameString.toLocal8Bit(); + const char* fileName = fileNameAscii.data(); - VoxelTree importVoxels; - if (fileNameString.endsWith(".png", Qt::CaseInsensitive)) { - QImage pngImage = QImage(fileName); - if (pngImage.height() != pngImage.width()) { - qDebug("ERROR: Bad PNG size: height != width.\n"); - return; + int fileTypeNameLength = 0; + VoxelTree importVoxels; + if (fileNameString.endsWith(".png", Qt::CaseInsensitive)) { + QImage pngImage = QImage(fileName); + fileTypeNameLength = PNG_TYPE_NAME_LENGTH; + if (pngImage.height() != pngImage.width()) { + qDebug("ERROR: Bad PNG size: height != width.\n"); + return; + } + + const uint32_t* pixels; + if (pngImage.format() == QImage::Format_ARGB32) { + pixels = reinterpret_cast(pngImage.constBits()); + } else { + QImage tmp = pngImage.convertToFormat(QImage::Format_ARGB32); + pixels = reinterpret_cast(tmp.constBits()); + } + + importVoxels.readFromSquareARGB32Pixels(pixels, pngImage.height()); + } else if (fileNameString.endsWith(".svo", Qt::CaseInsensitive)) { + importVoxels.readFromSVOFile(fileName); + fileTypeNameLength = SVO_TYPE_NAME_LENGTH; + } else if (fileNameString.endsWith(".schematic", Qt::CaseInsensitive)) { + importVoxels.readFromSchematicFile(fileName); + fileTypeNameLength = SCH_TYPE_NAME_LENGTH; } - const uint32_t* pixels; - if (pngImage.format() == QImage::Format_ARGB32) { - pixels = reinterpret_cast(pngImage.constBits()); + int indexOfFirstPeriod = fileNameString.indexOf('.'); + + QString fileCoord = fileNameString.mid(indexOfFirstPeriod + 1, + fileNameString.length() - indexOfFirstPeriod - fileTypeNameLength - 1); + + indexOfFirstPeriod = fileCoord.indexOf('.'); + QString columnNumString = fileCoord.right(fileCoord.length() - indexOfFirstPeriod - 1); + QString rowNumString = fileCoord.left(indexOfFirstPeriod); + + int columnNum = columnNumString.toFloat(); + int rowNum = rowNumString.toFloat(); + + qDebug("columnNum: %d\t rowNum: %d\n", columnNum, rowNum); + + _mouseVoxel.x = originalX + (columnNum - 1) * _mouseVoxel.s; + _mouseVoxel.z = originalZ + (rowNum - 1) * _mouseVoxel.s; + + VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + + // Recurse the Import Voxels tree, where everything is root relative, and send all the colored voxels to + // the server as an set voxel message, this will also rebase the voxels to the new location + unsigned char* calculatedOctCode = NULL; + SendVoxelsOperationArgs args; + args.lastSendTime = usecTimestampNow(); + args.packetsSent = 0; + args.bytesSent = 0; + + int numBytesPacketHeader = populateTypeAndVersion(args.messageBuffer, PACKET_TYPE_SET_VOXEL_DESTRUCTIVE); + + unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[numBytesPacketHeader]; + *sequenceAt = 0; + args.bufferInUse = numBytesPacketHeader + sizeof(unsigned short int); // set to command + sequence + + // we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the + // voxel size/position details. + if (selectedNode) { + args.newBaseOctCode = selectedNode->getOctalCode(); } else { - QImage tmp = pngImage.convertToFormat(QImage::Format_ARGB32); - pixels = reinterpret_cast(tmp.constBits()); + args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); + } + + qDebug("column:%d, row:%d, voxel:%f,%f,%f,%f\n", columnNum, rowNum, _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s ); + + // send the insert/paste of these voxels + importVoxels.recurseTreeWithOperation(sendVoxelsOperation, &args); + + // If we have voxels left in the packet, then send the packet + if (args.bufferInUse > (numBytesPacketHeader + sizeof(unsigned short int))) { + controlledBroadcastToNodes(args.messageBuffer, args.bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1); + + + args.packetsSent++; + args.bytesSent += args.bufferInUse; + + uint64_t now = usecTimestampNow(); + // dynamically sleep until we need to fire off the next set of voxels + uint64_t elapsed = now - args.lastSendTime; + int usecToSleep = CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS - elapsed; + + if (usecToSleep > 0) { + //qDebug("after sendVoxelsOperation: packet: %d bytes:%lld elapsed %lld usecs, sleeping for %d usecs!\n", + // args.packetsSent, (long long int)args.bytesSent, (long long int)elapsed, usecToSleep); + usleep(usecToSleep); + } else { + //qDebug("after sendVoxelsOperation: packet: %d bytes:%lld elapsed %lld usecs, no need to sleep!\n", + // args.packetsSent, (long long int)args.bytesSent, (long long int)elapsed); + } + args.lastSendTime = now; } - importVoxels.readFromSquareARGB32Pixels(pixels, pngImage.height()); - } else if (fileNameString.endsWith(".svo", Qt::CaseInsensitive)) { - importVoxels.readFromSVOFile(fileName); - } else if (fileNameString.endsWith(".schematic", Qt::CaseInsensitive)) { - importVoxels.readFromSchematicFile(fileName); + if (calculatedOctCode) { + delete[] calculatedOctCode; + } + } - VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); - - // Recurse the Import Voxels tree, where everything is root relative, and send all the colored voxels to - // the server as an set voxel message, this will also rebase the voxels to the new location - unsigned char* calculatedOctCode = NULL; - SendVoxelsOperationArgs args; - args.lastSendTime = usecTimestampNow(); - args.packetsSent = 0; - args.bytesSent = 0; - - int numBytesPacketHeader = populateTypeAndVersion(args.messageBuffer, PACKET_TYPE_SET_VOXEL_DESTRUCTIVE); - - unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[numBytesPacketHeader]; - *sequenceAt = 0; - args.bufferInUse = numBytesPacketHeader + sizeof(unsigned short int); // set to command + sequence - - // we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the - // voxel size/position details. - if (selectedNode) { - args.newBaseOctCode = selectedNode->getOctalCode(); - } else { - args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); - } - - importVoxels.recurseTreeWithOperation(sendVoxelsOperation, &args); - - // If we have voxels left in the packet, then send the packet - if (args.bufferInUse > (numBytesPacketHeader + sizeof(unsigned short int))) { - controlledBroadcastToNodes(args.messageBuffer, args.bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1); - } - - if (calculatedOctCode) { - delete[] calculatedOctCode; - } - // restore the main window's active state _window->activateWindow(); } @@ -3454,6 +3513,7 @@ void* Application::networkReceive(void* args) { } if (NodeList::getInstance()->getNodeSocket()->receive(&senderAddress, app->_incomingPacket, &bytesReceived)) { + app->_packetCount++; app->_bytesCount += bytesReceived; @@ -3498,13 +3558,11 @@ void* Application::networkReceive(void* args) { Node* voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER); if (voxelServer && socketMatch(voxelServer->getActiveSocket(), &senderAddress)) { voxelServer->lock(); - if (messageData[0] == PACKET_TYPE_ENVIRONMENT_DATA) { app->_environment.parseData(&senderAddress, messageData, messageLength); } else { app->_voxels.parseData(messageData, messageLength); } - voxelServer->unlock(); } } diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 55dff0c69a..4b971e9515 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -41,4 +41,6 @@ const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX; const float SIXTY_FPS_IN_MILLISECONDS = 1000.0f / 60.0f; const float VIEW_CULLING_RATE_IN_MILLISECONDS = 1000.0f; // once a second is fine +const uint64_t CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS = 1000 * 5; // 1 packet every 50 milliseconds + #endif \ No newline at end of file diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index c009eec2a5..d902f5dfeb 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -61,6 +61,7 @@ bool wantColorRandomizer = false; bool debugVoxelSending = false; bool shouldShowAnimationDebug = false; bool displayVoxelStats = false; +bool debugVoxelReceiving = false; EnvironmentData environmentData[3]; @@ -426,6 +427,8 @@ void attachVoxelNodeDataToNode(Node* newNode) { } } +int receivedPacketCount = 0; + int main(int argc, const char * argv[]) { pthread_mutex_init(&::treeLock, NULL); @@ -455,6 +458,10 @@ int main(int argc, const char * argv[]) { ::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING); printf("debugVoxelSending=%s\n", debug::valueOf(::debugVoxelSending)); + const char* DEBUG_VOXEL_RECEIVING = "--debugVoxelReceiving"; + ::debugVoxelReceiving = cmdOptionExists(argc, argv, DEBUG_VOXEL_RECEIVING); + printf("debugVoxelReceiving=%s\n", debug::valueOf(::debugVoxelReceiving)); + const char* WANT_ANIMATION_DEBUG = "--shouldShowAnimationDebug"; ::shouldShowAnimationDebug = cmdOptionExists(argc, argv, WANT_ANIMATION_DEBUG); printf("shouldShowAnimationDebug=%s\n", debug::valueOf(::shouldShowAnimationDebug)); @@ -584,12 +591,20 @@ int main(int argc, const char * argv[]) { destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL", ::shouldShowAnimationDebug); + ::receivedPacketCount++; + unsigned short int itemNumber = (*((unsigned short int*)(packetData + numBytesPacketHeader))); if (::shouldShowAnimationDebug) { printf("got %s - command from client receivedBytes=%ld itemNumber=%d\n", destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL", receivedBytes,itemNumber); } + + if (::debugVoxelReceiving) { + printf("got %s - %d command from client receivedBytes=%ld itemNumber=%d\n", + destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL", + ::receivedPacketCount, receivedBytes,itemNumber); + } int atByte = numBytesPacketHeader + sizeof(itemNumber); unsigned char* voxelData = (unsigned char*)&packetData[atByte]; while (atByte < receivedBytes) {