From 5415543dcd1e6654deb6b9d5c8b82aab6661a16a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 6 Apr 2013 12:03:46 -0700 Subject: [PATCH] adding Z command to voxel server and interface, Z command allows sending "erase all" and "add scene" commands --- interface/src/VoxelSystem.cpp | 23 ++++++++++++++ interface/src/main.cpp | 2 +- shared/src/VoxelTree.cpp | 10 +++++++ shared/src/VoxelTree.h | 2 ++ tools/sendvoxels.php | 26 ++++++++++++++-- voxel/src/main.cpp | 56 ++++++++++++++++++++++++++++++++++- 6 files changed, 115 insertions(+), 4 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 68914e2d6b..0f4d7bf7ca 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -97,6 +97,29 @@ void VoxelSystem::parseData(void *data, int size) { // ask the tree to read the "remove" bitstream tree->processRemoveVoxelBitstream((unsigned char*)data,size); break; + case 'Z': + + // the Z command is a special command that allows the sender to send high level semantic + // requests, like erase all, or add sphere scene, different receivers may handle these + // messages differently + char* packetData =(char*)data; + char* command = &packetData[1]; // start of the command + int commandLength = strlen(command); // commands are null terminated strings + int totalLength = 1+commandLength+1; + + printf("got Z message len(%d)= %s\n",size,command); + + while (totalLength <= size) { + if (0==strcmp(command,(char*)"erase all")) { + printf("got Z message == erase all\n"); + tree->eraseAllVoxels(); + } + if (0==strcmp(command,(char*)"add scene")) { + printf("got Z message == add scene - NOT SUPPORTED ON INTERFACE\n"); + } + totalLength += commandLength+1; + } + break; } setupNewVoxelsForDrawing(); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 9f005255cf..bd62bbf35d 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -901,7 +901,7 @@ void *networkReceive(void *args) if (incomingPacket[0] == 't') { // Pass everything but transmitter data to the agent list myHead.hand->processTransmitterData(incomingPacket, bytesReceived); - } else if (incomingPacket[0] == 'V' || incomingPacket[0] == 'R') { + } else if (incomingPacket[0] == 'V' || incomingPacket[0] == 'R' || incomingPacket[0] == 'Z') { voxels.parseData(incomingPacket, bytesReceived); } else { agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived); diff --git a/shared/src/VoxelTree.cpp b/shared/src/VoxelTree.cpp index a7390dd06f..7536bf9042 100644 --- a/shared/src/VoxelTree.cpp +++ b/shared/src/VoxelTree.cpp @@ -202,6 +202,16 @@ void VoxelTree::deleteVoxelCodeFromTree(unsigned char *codeBuffer) { } } +void VoxelTree::eraseAllVoxels() { + + // XXXBHG Hack attack - is there a better way to erase the voxel tree? + + delete rootNode; // this will recurse and delete all children + rootNode = new VoxelNode(); + rootNode->octalCode = new unsigned char[1]; + *rootNode->octalCode = 0; +} + void VoxelTree::readCodeColorBufferToTree(unsigned char *codeColorBuffer) { VoxelNode *lastCreatedNode = nodeForOctalCode(rootNode, codeColorBuffer, NULL); diff --git a/shared/src/VoxelTree.h b/shared/src/VoxelTree.h index 8a998a73bf..59f8e47eda 100644 --- a/shared/src/VoxelTree.h +++ b/shared/src/VoxelTree.h @@ -27,6 +27,8 @@ public: VoxelNode *rootNode; int leavesWrittenToBitstream; + void eraseAllVoxels(); + void processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes); void readBitstreamToTree(unsigned char * bitstream, int bufferSizeBytes); void readCodeColorBufferToTree(unsigned char *codeColorBuffer); diff --git a/tools/sendvoxels.php b/tools/sendvoxels.php index 69f0f798fc..b71c50c8df 100644 --- a/tools/sendvoxels.php +++ b/tools/sendvoxels.php @@ -38,13 +38,31 @@ function send_voxels($inputFileName,$server,$port,$command) { socket_close($socketHandle); } +function send_zcommand($server,$port,$command) { + $socketHandle = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); + $serverIP = $server; + $serverSendPort = $port; + + // [1:'Z'][2:command][0]... + $netData = pack("c",ord('Z')); + $netData .= $command; + $netData .= pack("c",0); + + $packetSize = 2+strlen($command); + echo "sending packet server=$serverIP port=$serverSendPort size=$packetSize \n"; + $result = socket_sendto($socketHandle, $netData, $packetSize, 0, $serverIP, $serverSendPort); + socket_close($socketHandle); +} + function testmode_send_voxels($server,$port) { echo "psych! test mode not implemented!\n"; } -$options = getopt("i:s:p:c:",array('testmode')); +$options = getopt("i:s:p:c:",array('testmode','zcommand:')); +//print_r($options); +//break; -if (empty($options['i']) || empty($options['i'])) { +if (empty($options['i']) && empty($options['zcommand'])) { echo "USAGE: sendvoxels.php -i 'inputFileName' -s [serverip] -p [port] -c [I|R] \n"; } else { $filename = $options['i']; @@ -54,6 +72,7 @@ if (empty($options['i']) || empty($options['i'])) { switch($command) { case 'I': case 'R': + case 'Z': //$command is good break; default: @@ -63,6 +82,9 @@ if (empty($options['i']) || empty($options['i'])) { if ($options['testmode']) { echo "TEST MODE Sending Voxels server:$server port:$port \n"; testmode_send_voxels($server,$port); + } else if ($options['zcommand'] && $command=='Z') { + echo "Sending Z command to server:$server port:$port \n"; + send_zcommand($server,$port,$options['zcommand']); } else { echo "Sending Voxels file:$filename server:$server port:$port command:$command \n"; send_voxels($filename,$server,$port,$command); diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index 0a2ae0c584..c3b955b22e 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -114,6 +114,33 @@ void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { } } +void eraseVoxelTreeAndCleanupAgentVisitData() { + + // As our tree to erase all it's voxels + ::randomTree.eraseAllVoxels(); + + // enumerate the agents clean up their marker nodes + for (int i = 0; i < agentList.getAgents().size(); i++) { + + //printf("eraseVoxelTreeAndCleanupAgentVisitData() agent[%d]\n",i); + + Agent *thisAgent = (Agent *)&::agentList.getAgents()[i]; + VoxelAgentData *agentData = (VoxelAgentData *)(thisAgent->getLinkedData()); + + // lock this agent's delete mutex so that the delete thread doesn't + // kill the agent while we are working with it + pthread_mutex_lock(&thisAgent->deleteMutex); + + // clean up the agent visit data + delete agentData->rootMarkerNode; + agentData->rootMarkerNode = new MarkerNode(); + + // unlock the delete mutex so the other thread can + // kill the agent if it has dissapeared + pthread_mutex_unlock(&thisAgent->deleteMutex); + } +} + void *distributeVoxelsToListeners(void *args) { timeval lastSendTime; @@ -133,7 +160,7 @@ void *distributeVoxelsToListeners(void *args) { // enumerate the agents to send 3 packets to each for (int i = 0; i < agentList.getAgents().size(); i++) { - + Agent *thisAgent = (Agent *)&agentList.getAgents()[i]; VoxelAgentData *agentData = (VoxelAgentData *)(thisAgent->getLinkedData()); @@ -319,6 +346,33 @@ int main(int argc, const char * argv[]) agentList.broadcastToAgents(packetData,receivedBytes,AgentList::AGENTS_OF_TYPE_HEAD); } + if (packetData[0] == 'Z') { + + // the Z command is a special command that allows the sender to send the voxel server high level semantic + // requests, like erase all, or add sphere scene + char* command = &packetData[1]; // start of the command + int commandLength = strlen(command); // commands are null terminated strings + int totalLength = 1+commandLength+1; + + printf("got Z message len(%ld)= %s\n",receivedBytes,command); + + while (totalLength <= receivedBytes) { + if (0==strcmp(command,(char*)"erase all")) { + printf("got Z message == erase all\n"); + + eraseVoxelTreeAndCleanupAgentVisitData(); + } + if (0==strcmp(command,(char*)"add scene")) { + printf("got Z message == add scene\n"); + addSphereScene(&randomTree,false); + } + totalLength += commandLength+1; + } + + // Now send this to the connected agents so they can also process these messages + printf("rebroadcasting Z message to connected agents... agentList.broadcastToAgents()\n"); + agentList.broadcastToAgents(packetData,receivedBytes,AgentList::AGENTS_OF_TYPE_HEAD); + } if (packetData[0] == 'H') { if (agentList.addOrUpdateAgent(&agentPublicAddress, &agentPublicAddress,