diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 5d61190286..ad01750aa1 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -25,9 +25,11 @@ link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) +link_hifi_library(voxel-server-library ${TARGET_NAME} ${ROOT_DIR}) # link the stk library set(STK_ROOT_DIR ${ROOT_DIR}/externals/stk) find_package(STK REQUIRED) target_link_libraries(${TARGET_NAME} ${STK_LIBRARIES}) -include_directories(${STK_INCLUDE_DIRS}) \ No newline at end of file +include_directories(${STK_INCLUDE_DIRS}) + diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 2ad8345e53..f58828e65f 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -22,6 +22,7 @@ #include <NodeList.h> #include <PacketHeaders.h> #include <SharedUtil.h> +#include <VoxelServer.h> const long long ASSIGNMENT_REQUEST_INTERVAL_USECS = 1 * 1000 * 1000; const char PARENT_TARGET_NAME[] = "assignment-client-monitor"; @@ -97,6 +98,8 @@ void childClient() { AudioMixer::run(); } else if (deployedAssignment.getType() == Assignment::AvatarMixerType) { AvatarMixer::run(); + } else if (deployedAssignment.getType() == Assignment::VoxelServerType) { + VoxelServer::run(); } else { // figure out the URL for the script for this agent assignment QString scriptURLString("http://%1:8080/assignment/%2"); diff --git a/domain-server/CMakeLists.txt b/domain-server/CMakeLists.txt index 1026f6c0b3..3c54a2d7f0 100644 --- a/domain-server/CMakeLists.txt +++ b/domain-server/CMakeLists.txt @@ -10,9 +10,9 @@ setup_hifi_project(${TARGET_NAME} TRUE) # setup a library for civetweb and link it to the domain-server FILE(GLOB CIVETWEB_SRCS external/civetweb/src/*.c) -add_library(CIVETWEB ${CIVETWEB_SRCS}) +add_library(civetweb ${CIVETWEB_SRCS}) include_directories(external/civetweb/include) -target_link_libraries(${TARGET_NAME} CIVETWEB) +target_link_libraries(${TARGET_NAME} civetweb) # remove and then copy the files for the webserver add_custom_command(TARGET ${TARGET_NAME} POST_BUILD @@ -25,4 +25,9 @@ add_custom_command(TARGET ${TARGET_NAME} POST_BUILD # link the shared hifi library include(${MACRO_DIR}/LinkHifiLibrary.cmake) -link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file +link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) + +# link dl library on UNIX for civetweb +if (UNIX AND NOT APPLE) + target_link_libraries(${TARGET_NAME} ${CMAKE_DL_LIBS}) +endif (UNIX AND NOT APPLE) \ No newline at end of file diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index b4b5c0ec36..3cb433b933 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -155,6 +155,10 @@ int main(int argc, const char* argv[]) { Assignment avatarMixerAssignment(Assignment::CreateCommand, Assignment::AvatarMixerType, Assignment::LocalLocation); + + Assignment voxelServerAssignment(Assignment::CreateCommand, + Assignment::VoxelServerType, + Assignment::LocalLocation); // construct a local socket to send with our created assignments to the global AS sockaddr_in localSocket = {}; @@ -168,8 +172,6 @@ int main(int argc, const char* argv[]) { QString documentRoot = QString("%1/resources/web").arg(QCoreApplication::applicationDirPath()); - qDebug() << documentRoot << "\n"; - // list of options. Last element must be NULL. const char *options[] = {"listening_ports", "8080", "document_root", documentRoot.toStdString().c_str(), NULL}; @@ -180,6 +182,9 @@ int main(int argc, const char* argv[]) { // Start the web server. ctx = mg_start(&callbacks, NULL, options); + // wait to check on voxel-servers till we've given our NodeList a chance to get a good list + int checkForVoxelServerAttempt = 0; + while (true) { ::assignmentQueueMutex.lock(); @@ -196,6 +201,27 @@ int main(int argc, const char* argv[]) { qDebug("Missing an audio mixer and assignment not in queue. Adding.\n"); ::assignmentQueue.push_front(&audioMixerAssignment); } + + // Now handle voxel servers. Couple of things are special about voxel servers. + // 1) They can run standalone, and so we want to wait to ask for an assignment until we've given them sufficient + // time to check in with us. So we will look for them, but we want actually add assignments unless we haven't + // seen one after a few tries. + // 2) They aren't soloNodeOfType() so we have to count them. + int voxelServerCount = 0; + for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + if (node->getType() == NODE_TYPE_VOXEL_SERVER) { + voxelServerCount++; + } + } + const int MIN_VOXEL_SERVER_CHECKS = 10; + if (checkForVoxelServerAttempt > MIN_VOXEL_SERVER_CHECKS && + voxelServerCount == 0 && + std::find(::assignmentQueue.begin(), ::assignmentQueue.end(), &voxelServerAssignment) == ::assignmentQueue.end()) { + qDebug("Missing a Voxel Server and assignment not in queue. Adding.\n"); + ::assignmentQueue.push_front(&voxelServerAssignment); + } + checkForVoxelServerAttempt++; + ::assignmentQueueMutex.unlock(); while (nodeList->getNodeSocket()->receive((sockaddr *)&nodePublicAddress, packetData, &receivedBytes) && diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 084b1f8c85..0df2f2d41c 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -723,7 +723,7 @@ void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { // Always render other people, and render myself when beyond threshold distance if (b == BODY_BALL_HEAD_BASE) { // the head is rendered as a special if (alpha > 0.0f) { - _head.render(alpha); + _head.render(alpha, false); } } else if (alpha > 0.0f) { // Render the body ball sphere @@ -767,7 +767,7 @@ void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, lookingInMirror); if (alpha > 0.0f) { _voxels.render(false); - _head.render(alpha); + _head.render(alpha, false); } } _hand.render(lookingInMirror); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index af6133460f..9c86f92e2b 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -322,7 +322,7 @@ void Head::calculateGeometry() { + up * _scale * NOSE_UPTURN; } -void Head::render(float alpha) { +void Head::render(float alpha, bool isMine) { _renderAlpha = alpha; if (!_face.render(alpha)) { @@ -331,7 +331,7 @@ void Head::render(float alpha) { glEnable(GL_DEPTH_TEST); glEnable(GL_RESCALE_NORMAL); - if (Menu::getInstance()->isOptionChecked(MenuOption::UsePerlinFace)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::UsePerlinFace) && isMine) { _perlinFace.render(); } else { renderMohawk(); diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 496fdecef6..90d4507c7b 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -43,7 +43,7 @@ public: void init(); void reset(); void simulate(float deltaTime, bool isMine, float gyroCameraSensitivity); - void render(float alpha); + void render(float alpha, bool isMine); void renderMohawk(); void setScale(float scale); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0dcfe32236..c9d0dd37bc 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -557,7 +557,7 @@ void MyAvatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { // Always render other people, and render myself when beyond threshold distance if (b == BODY_BALL_HEAD_BASE) { // the head is rendered as a special if (alpha > 0.0f) { - _head.render(alpha); + _head.render(alpha, true); } } else if (alpha > 0.0f) { // Render the body ball sphere @@ -614,7 +614,7 @@ void MyAvatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, lookingInMirror); if (alpha > 0.0f) { _voxels.render(false); - _head.render(alpha); + _head.render(alpha, true); } } _hand.render(lookingInMirror); diff --git a/interface/src/devices/Faceshift.cpp b/interface/src/devices/Faceshift.cpp index cc86785e60..e1480e39d2 100644 --- a/interface/src/devices/Faceshift.cpp +++ b/interface/src/devices/Faceshift.cpp @@ -28,6 +28,10 @@ Faceshift::Faceshift() : _rightBlink(0.0f), _leftEyeOpen(0.0f), _rightEyeOpen(0.0f), + _leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes + _rightBlinkIndex(1), + _leftEyeOpenIndex(8), + _rightEyeOpenIndex(9), _browDownLeft(0.0f), _browDownRight(0.0f), _browUpCenter(0.0f), @@ -35,6 +39,7 @@ Faceshift::Faceshift() : _browUpRight(0.0f), _browDownLeftIndex(-1), _browDownRightIndex(-1), + _browUpCenterIndex(16), _browUpLeftIndex(-1), _browUpRightIndex(-1), _mouthSize(0.0f), @@ -42,11 +47,6 @@ Faceshift::Faceshift() : _mouthSmileRight(0), _mouthSmileLeftIndex(-1), _mouthSmileRightIndex(0), - _leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes - _rightBlinkIndex(1), - _leftEyeOpenIndex(8), - _rightEyeOpenIndex(9), - _browUpCenterIndex(16), _jawOpenIndex(21), _longTermAverageEyePitch(0.0f), _longTermAverageEyeYaw(0.0f), diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index dc246a9ad6..59e2c45db7 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -23,6 +23,7 @@ public: AudioMixerType, AvatarMixerType, AgentType, + VoxelServerType, AllTypes }; diff --git a/libraries/voxel-server-library/CMakeLists.txt b/libraries/voxel-server-library/CMakeLists.txt new file mode 100644 index 0000000000..9eabb95508 --- /dev/null +++ b/libraries/voxel-server-library/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 2.8) + +set(ROOT_DIR ../..) +set(MACRO_DIR ${ROOT_DIR}/cmake/macros) + +# setup for find modules +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/") + +set(TARGET_NAME voxel-server-library) + +find_package(Qt5Widgets REQUIRED) + +include(${MACRO_DIR}/SetupHifiLibrary.cmake) +setup_hifi_library(${TARGET_NAME}) + +qt5_use_modules(${TARGET_NAME} Widgets) + +include(${MACRO_DIR}/IncludeGLM.cmake) +include_glm(${TARGET_NAME} ${ROOT_DIR}) + +include(${MACRO_DIR}/LinkHifiLibrary.cmake) +link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) + +# link ZLIB +find_package(ZLIB) +include_directories(${ZLIB_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) + +# link in the shared library +include(${MACRO_DIR}/LinkHifiLibrary.cmake) +link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) + +# link in the hifi voxels library +link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) + +# link in the hifi avatars library +link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) diff --git a/voxel-server/src/NodeWatcher.cpp b/libraries/voxel-server-library/src/NodeWatcher.cpp similarity index 100% rename from voxel-server/src/NodeWatcher.cpp rename to libraries/voxel-server-library/src/NodeWatcher.cpp diff --git a/voxel-server/src/NodeWatcher.h b/libraries/voxel-server-library/src/NodeWatcher.h similarity index 100% rename from voxel-server/src/NodeWatcher.h rename to libraries/voxel-server-library/src/NodeWatcher.h diff --git a/voxel-server/src/VoxelNodeData.cpp b/libraries/voxel-server-library/src/VoxelNodeData.cpp similarity index 100% rename from voxel-server/src/VoxelNodeData.cpp rename to libraries/voxel-server-library/src/VoxelNodeData.cpp diff --git a/voxel-server/src/VoxelNodeData.h b/libraries/voxel-server-library/src/VoxelNodeData.h similarity index 100% rename from voxel-server/src/VoxelNodeData.h rename to libraries/voxel-server-library/src/VoxelNodeData.h diff --git a/voxel-server/src/VoxelPersistThread.cpp b/libraries/voxel-server-library/src/VoxelPersistThread.cpp similarity index 100% rename from voxel-server/src/VoxelPersistThread.cpp rename to libraries/voxel-server-library/src/VoxelPersistThread.cpp diff --git a/voxel-server/src/VoxelPersistThread.h b/libraries/voxel-server-library/src/VoxelPersistThread.h similarity index 100% rename from voxel-server/src/VoxelPersistThread.h rename to libraries/voxel-server-library/src/VoxelPersistThread.h diff --git a/voxel-server/src/VoxelSendThread.cpp b/libraries/voxel-server-library/src/VoxelSendThread.cpp similarity index 99% rename from voxel-server/src/VoxelSendThread.cpp rename to libraries/voxel-server-library/src/VoxelSendThread.cpp index 38f8c6f9b8..b9bb861349 100644 --- a/voxel-server/src/VoxelSendThread.cpp +++ b/libraries/voxel-server-library/src/VoxelSendThread.cpp @@ -11,9 +11,12 @@ #include <NodeList.h> #include <SharedUtil.h> #include <PacketHeaders.h> +#include <EnvironmentData.h> +extern EnvironmentData environmentData[3]; #include "VoxelSendThread.h" #include "VoxelServer.h" +#include "VoxelServerState.h" VoxelSendThread::VoxelSendThread(uint16_t nodeID) : _nodeID(nodeID) { diff --git a/voxel-server/src/VoxelSendThread.h b/libraries/voxel-server-library/src/VoxelSendThread.h similarity index 100% rename from voxel-server/src/VoxelSendThread.h rename to libraries/voxel-server-library/src/VoxelSendThread.h diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp new file mode 100644 index 0000000000..b239a180d9 --- /dev/null +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -0,0 +1,349 @@ +// +// VoxelServer.cpp +// hifi +// +// Created by Brad Hefta-Gaub on 9/16/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include <cmath> +#include <cstdlib> +#include <cstring> +#include <cstdio> + +#include <OctalCode.h> +#include <NodeList.h> +#include <NodeTypes.h> +#include <EnvironmentData.h> +#include <VoxelTree.h> +#include "VoxelNodeData.h" +#include <SharedUtil.h> +#include <PacketHeaders.h> +#include <SceneUtils.h> +#include <PerfStat.h> +#include <JurisdictionSender.h> + +#include "NodeWatcher.h" +#include "VoxelPersistThread.h" +#include "VoxelSendThread.h" +#include "VoxelServerPacketProcessor.h" + +#ifdef _WIN32 +#include "Syssocket.h" +#include "Systime.h" +#else +#include <sys/time.h> +#include <arpa/inet.h> +#include <ifaddrs.h> +#endif + +#include "VoxelServer.h" +#include "VoxelServerState.h" + +const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo"; +const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.svo"; +char voxelPersistFilename[MAX_FILENAME_LENGTH]; +int PACKETS_PER_CLIENT_PER_INTERVAL = 10; +VoxelTree serverTree(true); // this IS a reaveraging tree +bool wantVoxelPersist = true; +bool wantLocalDomain = false; +bool debugVoxelSending = false; +bool shouldShowAnimationDebug = false; +bool displayVoxelStats = false; +bool debugVoxelReceiving = false; +bool sendEnvironments = true; +bool sendMinimalEnvironment = false; +bool dumpVoxelsOnMove = false; +EnvironmentData environmentData[3]; +int receivedPacketCount = 0; +JurisdictionMap* jurisdiction = NULL; +JurisdictionSender* jurisdictionSender = NULL; +VoxelServerPacketProcessor* voxelServerPacketProcessor = NULL; +VoxelPersistThread* voxelPersistThread = NULL; +pthread_mutex_t treeLock; +NodeWatcher nodeWatcher; // used to cleanup AGENT data when agents are killed + +int VoxelServer::_argc = 0; +const char** VoxelServer::_argv = NULL; +bool VoxelServer::_dontKillOnMissingDomain = false; + +void attachVoxelNodeDataToNode(Node* newNode) { + if (newNode->getLinkedData() == NULL) { + newNode->setLinkedData(new VoxelNodeData(newNode)); + } +} + +void VoxelServer::setArguments(int argc, char** argv) { + _argc = argc; + _argv = const_cast<const char**>(argv); +} + +void VoxelServer::setupDomainAndPort(const char* domain, int port) { + NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, port); + + // Handle Local Domain testing with the --local command line + const char* local = "--local"; + ::wantLocalDomain = strcmp(domain, local) == 0; + if (::wantLocalDomain) { + printf("Local Domain MODE!\n"); + NodeList::getInstance()->setDomainIPToLocalhost(); + } else { + if (domain) { + NodeList::getInstance()->setDomainHostname(domain); + } + } + + // If we're running in standalone mode, we don't want to kill ourselves when we haven't heard from a domain + _dontKillOnMissingDomain = true; +} + +//int main(int argc, const char * argv[]) { +void VoxelServer::run() { + pthread_mutex_init(&::treeLock, NULL); + + qInstallMessageHandler(sharedMessageHandler); + + const char* JURISDICTION_FILE = "--jurisdictionFile"; + const char* jurisdictionFile = getCmdOption(_argc, _argv, JURISDICTION_FILE); + if (jurisdictionFile) { + printf("jurisdictionFile=%s\n", jurisdictionFile); + + printf("about to readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); + jurisdiction = new JurisdictionMap(jurisdictionFile); + printf("after readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); + } else { + const char* JURISDICTION_ROOT = "--jurisdictionRoot"; + const char* jurisdictionRoot = getCmdOption(_argc, _argv, JURISDICTION_ROOT); + if (jurisdictionRoot) { + printf("jurisdictionRoot=%s\n", jurisdictionRoot); + } + + const char* JURISDICTION_ENDNODES = "--jurisdictionEndNodes"; + const char* jurisdictionEndNodes = getCmdOption(_argc, _argv, JURISDICTION_ENDNODES); + if (jurisdictionEndNodes) { + printf("jurisdictionEndNodes=%s\n", jurisdictionEndNodes); + } + + if (jurisdictionRoot || jurisdictionEndNodes) { + ::jurisdiction = new JurisdictionMap(jurisdictionRoot, jurisdictionEndNodes); + } + } + + // should we send environments? Default is yes, but this command line suppresses sending + const char* DUMP_VOXELS_ON_MOVE = "--dumpVoxelsOnMove"; + ::dumpVoxelsOnMove = cmdOptionExists(_argc, _argv, DUMP_VOXELS_ON_MOVE); + printf("dumpVoxelsOnMove=%s\n", debug::valueOf(::dumpVoxelsOnMove)); + + // should we send environments? Default is yes, but this command line suppresses sending + const char* DONT_SEND_ENVIRONMENTS = "--dontSendEnvironments"; + bool dontSendEnvironments = getCmdOption(_argc, _argv, DONT_SEND_ENVIRONMENTS); + if (dontSendEnvironments) { + printf("Sending environments suppressed...\n"); + ::sendEnvironments = false; + } else { + // should we send environments? Default is yes, but this command line suppresses sending + const char* MINIMAL_ENVIRONMENT = "--MinimalEnvironment"; + ::sendMinimalEnvironment = getCmdOption(_argc, _argv, MINIMAL_ENVIRONMENT); + printf("Using Minimal Environment=%s\n", debug::valueOf(::sendMinimalEnvironment)); + } + printf("Sending environments=%s\n", debug::valueOf(::sendEnvironments)); + + NodeList* nodeList = NodeList::getInstance(); + nodeList->setOwnerType(NODE_TYPE_VOXEL_SERVER); + + setvbuf(stdout, NULL, _IOLBF, 0); + + // tell our NodeList about our desire to get notifications + nodeList->addHook(&nodeWatcher); + nodeList->linkedDataCreateCallback = &attachVoxelNodeDataToNode; + + nodeList->startSilentNodeRemovalThread(); + srand((unsigned)time(0)); + + const char* DISPLAY_VOXEL_STATS = "--displayVoxelStats"; + ::displayVoxelStats = getCmdOption(_argc, _argv, DISPLAY_VOXEL_STATS); + printf("displayVoxelStats=%s\n", debug::valueOf(::displayVoxelStats)); + + const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending"; + ::debugVoxelSending = getCmdOption(_argc, _argv, DEBUG_VOXEL_SENDING); + printf("debugVoxelSending=%s\n", debug::valueOf(::debugVoxelSending)); + + const char* DEBUG_VOXEL_RECEIVING = "--debugVoxelReceiving"; + ::debugVoxelReceiving = getCmdOption(_argc, _argv, DEBUG_VOXEL_RECEIVING); + printf("debugVoxelReceiving=%s\n", debug::valueOf(::debugVoxelReceiving)); + + const char* WANT_ANIMATION_DEBUG = "--shouldShowAnimationDebug"; + ::shouldShowAnimationDebug = getCmdOption(_argc, _argv, WANT_ANIMATION_DEBUG); + printf("shouldShowAnimationDebug=%s\n", debug::valueOf(::shouldShowAnimationDebug)); + + // By default we will voxel persist, if you want to disable this, then pass in this parameter + const char* NO_VOXEL_PERSIST = "--NoVoxelPersist"; + if ( getCmdOption(_argc, _argv, NO_VOXEL_PERSIST)) { + ::wantVoxelPersist = false; + } + printf("wantVoxelPersist=%s\n", debug::valueOf(::wantVoxelPersist)); + + // if we want Voxel Persistence, load the local file now... + bool persistantFileRead = false; + if (::wantVoxelPersist) { + + // Check to see if the user passed in a command line option for setting packet send rate + const char* VOXELS_PERSIST_FILENAME = "--voxelsPersistFilename"; + const char* voxelsPersistFilenameParameter = getCmdOption(_argc, _argv, VOXELS_PERSIST_FILENAME); + if (voxelsPersistFilenameParameter) { + strcpy(voxelPersistFilename, voxelsPersistFilenameParameter); + } else { + //strcpy(voxelPersistFilename, ::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); + strcpy(voxelPersistFilename, LOCAL_VOXELS_PERSIST_FILE); + } + + printf("loading voxels from file: %s...\n", voxelPersistFilename); + + persistantFileRead = ::serverTree.readFromSVOFile(::voxelPersistFilename); + if (persistantFileRead) { + PerformanceWarning warn(::shouldShowAnimationDebug, + "persistVoxelsWhenDirty() - reaverageVoxelColors()", ::shouldShowAnimationDebug); + + // after done inserting all these voxels, then reaverage colors + serverTree.reaverageVoxelColors(serverTree.rootNode); + printf("Voxels reAveraged\n"); + } + + ::serverTree.clearDirtyBit(); // the tree is clean since we just loaded it + printf("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead)); + unsigned long nodeCount = ::serverTree.rootNode->getSubTreeNodeCount(); + unsigned long internalNodeCount = ::serverTree.rootNode->getSubTreeInternalNodeCount(); + unsigned long leafNodeCount = ::serverTree.rootNode->getSubTreeLeafNodeCount(); + printf("Nodes after loading scene %lu nodes %lu internal %lu leaves\n", nodeCount, internalNodeCount, leafNodeCount); + + // now set up VoxelPersistThread + ::voxelPersistThread = new VoxelPersistThread(&::serverTree, ::voxelPersistFilename); + if (::voxelPersistThread) { + ::voxelPersistThread->initialize(true); + } + } + + // Check to see if the user passed in a command line option for loading an old style local + // Voxel File. If so, load it now. This is not the same as a voxel persist file + const char* INPUT_FILE = "-i"; + const char* voxelsFilename = getCmdOption(_argc, _argv, INPUT_FILE); + if (voxelsFilename) { + serverTree.readFromSVOFile(voxelsFilename); + } + + // Check to see if the user passed in a command line option for setting packet send rate + const char* PACKETS_PER_SECOND = "--packetsPerSecond"; + const char* packetsPerSecond = getCmdOption(_argc, _argv, PACKETS_PER_SECOND); + if (packetsPerSecond) { + PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/INTERVALS_PER_SECOND; + if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) { + PACKETS_PER_CLIENT_PER_INTERVAL = 1; + } + printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL); + } + + // for now, initialize the environments with fixed values + environmentData[1].setID(1); + environmentData[1].setGravity(1.0f); + environmentData[1].setAtmosphereCenter(glm::vec3(0.5, 0.5, (0.25 - 0.06125)) * (float)TREE_SCALE); + environmentData[1].setAtmosphereInnerRadius(0.030625f * TREE_SCALE); + environmentData[1].setAtmosphereOuterRadius(0.030625f * TREE_SCALE * 1.05f); + environmentData[2].setID(2); + environmentData[2].setGravity(1.0f); + environmentData[2].setAtmosphereCenter(glm::vec3(0.5f, 0.5f, 0.5f) * (float)TREE_SCALE); + environmentData[2].setAtmosphereInnerRadius(0.1875f * TREE_SCALE); + environmentData[2].setAtmosphereOuterRadius(0.1875f * TREE_SCALE * 1.05f); + environmentData[2].setScatteringWavelengths(glm::vec3(0.475f, 0.570f, 0.650f)); // swaps red and blue + + sockaddr senderAddress; + + unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE]; + ssize_t packetLength; + + timeval lastDomainServerCheckIn = {}; + + // set up our jurisdiction broadcaster... + ::jurisdictionSender = new JurisdictionSender(::jurisdiction); + if (::jurisdictionSender) { + ::jurisdictionSender->initialize(true); + } + + // set up our VoxelServerPacketProcessor + ::voxelServerPacketProcessor = new VoxelServerPacketProcessor(); + if (::voxelServerPacketProcessor) { + ::voxelServerPacketProcessor->initialize(true); + } + + // loop to send to nodes requesting data + while (true) { + + if (!_dontKillOnMissingDomain && + NodeList::getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) { + break; + } + + // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed + if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { + gettimeofday(&lastDomainServerCheckIn, NULL); + NodeList::getInstance()->sendDomainServerCheckIn(); + } + + if (nodeList->getNodeSocket()->receive(&senderAddress, packetData, &packetLength) && + packetVersionMatch(packetData)) { + + int numBytesPacketHeader = numBytesForPacketHeader(packetData); + + if (packetData[0] == PACKET_TYPE_HEAD_DATA) { + // If we got a PACKET_TYPE_HEAD_DATA, then we're talking to an NODE_TYPE_AVATAR, and we + // need to make sure we have it in our nodeList. + uint16_t nodeID = 0; + unpackNodeId(packetData + numBytesPacketHeader, &nodeID); + Node* node = NodeList::getInstance()->addOrUpdateNode(&senderAddress, + &senderAddress, + NODE_TYPE_AGENT, + nodeID); + + NodeList::getInstance()->updateNodeWithData(node, packetData, packetLength); + } else if (packetData[0] == PACKET_TYPE_PING) { + // If the packet is a ping, let processNodeData handle it. + NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); + } else if (packetData[0] == PACKET_TYPE_DOMAIN) { + NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); + } else if (packetData[0] == PACKET_TYPE_VOXEL_JURISDICTION_REQUEST) { + if (::jurisdictionSender) { + ::jurisdictionSender->queueReceivedPacket(senderAddress, packetData, packetLength); + } + } else if (::voxelServerPacketProcessor) { + ::voxelServerPacketProcessor->queueReceivedPacket(senderAddress, packetData, packetLength); + } else { + printf("unknown packet ignored... packetData[0]=%c\n", packetData[0]); + } + } + } + + if (::jurisdiction) { + delete ::jurisdiction; + } + + if (::jurisdictionSender) { + ::jurisdictionSender->terminate(); + delete ::jurisdictionSender; + } + + if (::voxelServerPacketProcessor) { + ::voxelServerPacketProcessor->terminate(); + delete ::voxelServerPacketProcessor; + } + + if (::voxelPersistThread) { + ::voxelPersistThread->terminate(); + delete ::voxelPersistThread; + } + + // tell our NodeList we're done with notifications + nodeList->removeHook(&nodeWatcher); + + pthread_mutex_destroy(&::treeLock); +} + + diff --git a/libraries/voxel-server-library/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServer.h new file mode 100644 index 0000000000..d51870dbb1 --- /dev/null +++ b/libraries/voxel-server-library/src/VoxelServer.h @@ -0,0 +1,36 @@ +// VoxelServer.h +// voxel-server +// +// Created by Brad Hefta-Gaub on 8/21/13 +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// +// + +#ifndef __voxel_server__VoxelServer__ +#define __voxel_server__VoxelServer__ + +/// Handles assignments of type VoxelServer - sending voxels to various clients. +class VoxelServer { +public: + /// runs the voxel server assignment + static void run(); + + /// allows setting of run arguments + static void setArguments(int argc, char** argv); + + /// when VoxelServer class is used by voxel-server stand alone executable it calls this to specify the domain + /// and port it is handling. When called by assignment-client, this is not needed because assignment-client + /// handles ports and domains automatically. + /// \param const char* domain domain name, IP address, or local to specify the domain the voxel server is serving + /// \param int port port the voxel server will listen on + static void setupDomainAndPort(const char* domain, int port); + +private: + static int _argc; + static const char** _argv; + static bool _dontKillOnMissingDomain; +}; + + + +#endif // __voxel_server__VoxelServer__ diff --git a/voxel-server/src/VoxelServerPacketProcessor.cpp b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp similarity index 99% rename from voxel-server/src/VoxelServerPacketProcessor.cpp rename to libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp index aaa347ee86..d283296e6f 100644 --- a/voxel-server/src/VoxelServerPacketProcessor.cpp +++ b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.cpp @@ -12,6 +12,7 @@ #include <PerfStat.h> #include "VoxelServer.h" +#include "VoxelServerState.h" #include "VoxelServerPacketProcessor.h" diff --git a/voxel-server/src/VoxelServerPacketProcessor.h b/libraries/voxel-server-library/src/VoxelServerPacketProcessor.h similarity index 100% rename from voxel-server/src/VoxelServerPacketProcessor.h rename to libraries/voxel-server-library/src/VoxelServerPacketProcessor.h diff --git a/voxel-server/src/VoxelServer.h b/libraries/voxel-server-library/src/VoxelServerState.h similarity index 88% rename from voxel-server/src/VoxelServer.h rename to libraries/voxel-server-library/src/VoxelServerState.h index 0f4c8577db..2d00d4a046 100644 --- a/voxel-server/src/VoxelServer.h +++ b/libraries/voxel-server-library/src/VoxelServerState.h @@ -6,12 +6,11 @@ // // -#ifndef __voxel_server__VoxelServer__ -#define __voxel_server__VoxelServer__ +#ifndef __voxel_server__VoxelServerState__ +#define __voxel_server__VoxelServerState__ #include <SharedUtil.h> #include <NodeList.h> // for MAX_PACKET_SIZE -#include <EnvironmentData.h> #include <JurisdictionSender.h> #include <VoxelTree.h> @@ -19,7 +18,6 @@ const int MAX_FILENAME_LENGTH = 1024; -const int VOXEL_LISTEN_PORT = 40106; const int VOXEL_SIZE_BYTES = 3 + (3 * sizeof(float)); const int VOXELS_PER_PACKET = (MAX_PACKET_SIZE - 1) / VOXEL_SIZE_BYTES; const int MIN_BRIGHTNESS = 64; @@ -46,13 +44,10 @@ extern bool debugVoxelReceiving; extern bool sendEnvironments; extern bool sendMinimalEnvironment; extern bool dumpVoxelsOnMove; -extern EnvironmentData environmentData[3]; extern int receivedPacketCount; extern JurisdictionMap* jurisdiction; extern JurisdictionSender* jurisdictionSender; extern VoxelServerPacketProcessor* voxelServerPacketProcessor; extern pthread_mutex_t treeLock; - - -#endif // __voxel_server__VoxelServer__ +#endif // __voxel_server__VoxelServerState__ diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 5a5815b6b3..08fdbefee3 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -24,8 +24,10 @@ const glm::vec3 IDENTITY_FRONT = glm::vec3( 0.0f, 0.0f,-1.0f); const bool LOW_RES_MONO = false; // while in "low res mode" do voxels switch to monochrome const uint64_t CHANGE_FUDGE = 1000 * 200; // useconds of fudge in determining if we want to resend changed voxels -const int TREE_SCALE = 128; // This is the number of meters of the 0.0 to 1.0 voxel universe -const float VOXEL_SIZE_SCALE = 50000.0f; // This controls the LOD bigger will make smaller voxels visible at greater distance +const int TREE_SCALE = 16384; // ~10 miles.. This is the number of meters of the 0.0 to 1.0 voxel universe + +// This controls the LOD. Larger number will make smaller voxels visible at greater distance. +const float VOXEL_SIZE_SCALE = TREE_SCALE * 400.0f; const int NUMBER_OF_CHILDREN = 8; const int MAX_VOXEL_PACKET_SIZE = 1492; diff --git a/voxel-server/CMakeLists.txt b/voxel-server/CMakeLists.txt index c401a8033c..f759db0d89 100644 --- a/voxel-server/CMakeLists.txt +++ b/voxel-server/CMakeLists.txt @@ -26,3 +26,5 @@ link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) # link in the hifi avatars library link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) +# link in the hifi voxel-server-library +link_hifi_library(voxel-server-library ${TARGET_NAME} ${ROOT_DIR}) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 56ea5003e1..f854df84cf 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -6,73 +6,18 @@ // Copyright (c) 2012 High Fidelity, Inc. All rights reserved. // -#include <cmath> -#include <cstdlib> -#include <cstring> -#include <cstdio> - -#include <OctalCode.h> -#include <NodeList.h> -#include <NodeTypes.h> -#include <EnvironmentData.h> -#include <VoxelTree.h> -#include "VoxelNodeData.h" #include <SharedUtil.h> -#include <PacketHeaders.h> -#include <SceneUtils.h> -#include <PerfStat.h> -#include <JurisdictionSender.h> +#include <VoxelServer.h> +const int VOXEL_LISTEN_PORT = 40106; -#include "NodeWatcher.h" -#include "VoxelPersistThread.h" -#include "VoxelSendThread.h" -#include "VoxelServerPacketProcessor.h" - -#ifdef _WIN32 -#include "Syssocket.h" -#include "Systime.h" -#else -#include <sys/time.h> -#include <arpa/inet.h> -#include <ifaddrs.h> -#endif - -#include "VoxelServer.h" - -const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo"; -const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.svo"; -char voxelPersistFilename[MAX_FILENAME_LENGTH]; -int PACKETS_PER_CLIENT_PER_INTERVAL = 10; -VoxelTree serverTree(true); // this IS a reaveraging tree -bool wantVoxelPersist = true; -bool wantLocalDomain = false; -bool debugVoxelSending = false; -bool shouldShowAnimationDebug = false; -bool displayVoxelStats = false; -bool debugVoxelReceiving = false; -bool sendEnvironments = true; -bool sendMinimalEnvironment = false; -bool dumpVoxelsOnMove = false; -EnvironmentData environmentData[3]; -int receivedPacketCount = 0; -JurisdictionMap* jurisdiction = NULL; -JurisdictionSender* jurisdictionSender = NULL; -VoxelServerPacketProcessor* voxelServerPacketProcessor = NULL; -VoxelPersistThread* voxelPersistThread = NULL; -pthread_mutex_t treeLock; -NodeWatcher nodeWatcher; // used to cleanup AGENT data when agents are killed - -void attachVoxelNodeDataToNode(Node* newNode) { - if (newNode->getLinkedData() == NULL) { - newNode->setLinkedData(new VoxelNodeData(newNode)); - } -} int main(int argc, const char * argv[]) { - pthread_mutex_init(&::treeLock, NULL); - - qInstallMessageHandler(sharedMessageHandler); - + + // Handle Local Domain testing with the --local command line + const char* local = "--local"; + bool wantLocalDomain = cmdOptionExists(argc, argv, local); + const char* domainIP = getCmdOption(argc, argv, "--domain"); + int listenPort = VOXEL_LISTEN_PORT; // Check to see if the user passed in a command line option for setting listen port const char* PORT_PARAMETER = "--port"; @@ -85,255 +30,16 @@ int main(int argc, const char * argv[]) { printf("portParameter=%s listenPort=%d\n", portParameter, listenPort); } - const char* JURISDICTION_FILE = "--jurisdictionFile"; - const char* jurisdictionFile = getCmdOption(argc, argv, JURISDICTION_FILE); - if (jurisdictionFile) { - printf("jurisdictionFile=%s\n", jurisdictionFile); - - printf("about to readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); - jurisdiction = new JurisdictionMap(jurisdictionFile); - printf("after readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); + if (wantLocalDomain) { + VoxelServer::setupDomainAndPort(local, listenPort); } else { - const char* JURISDICTION_ROOT = "--jurisdictionRoot"; - const char* jurisdictionRoot = getCmdOption(argc, argv, JURISDICTION_ROOT); - if (jurisdictionRoot) { - printf("jurisdictionRoot=%s\n", jurisdictionRoot); - } - - const char* JURISDICTION_ENDNODES = "--jurisdictionEndNodes"; - const char* jurisdictionEndNodes = getCmdOption(argc, argv, JURISDICTION_ENDNODES); - if (jurisdictionEndNodes) { - printf("jurisdictionEndNodes=%s\n", jurisdictionEndNodes); - } - - if (jurisdictionRoot || jurisdictionEndNodes) { - ::jurisdiction = new JurisdictionMap(jurisdictionRoot, jurisdictionEndNodes); - } - } - - // should we send environments? Default is yes, but this command line suppresses sending - const char* DUMP_VOXELS_ON_MOVE = "--dumpVoxelsOnMove"; - ::dumpVoxelsOnMove = cmdOptionExists(argc, argv, DUMP_VOXELS_ON_MOVE); - printf("dumpVoxelsOnMove=%s\n", debug::valueOf(::dumpVoxelsOnMove)); - - // should we send environments? Default is yes, but this command line suppresses sending - const char* DONT_SEND_ENVIRONMENTS = "--dontSendEnvironments"; - bool dontSendEnvironments = cmdOptionExists(argc, argv, DONT_SEND_ENVIRONMENTS); - if (dontSendEnvironments) { - printf("Sending environments suppressed...\n"); - ::sendEnvironments = false; - } else { - // should we send environments? Default is yes, but this command line suppresses sending - const char* MINIMAL_ENVIRONMENT = "--MinimalEnvironment"; - ::sendMinimalEnvironment = cmdOptionExists(argc, argv, MINIMAL_ENVIRONMENT); - printf("Using Minimal Environment=%s\n", debug::valueOf(::sendMinimalEnvironment)); - } - printf("Sending environments=%s\n", debug::valueOf(::sendEnvironments)); - - NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, listenPort); - setvbuf(stdout, NULL, _IOLBF, 0); - - // tell our NodeList about our desire to get notifications - nodeList->addHook(&nodeWatcher); - - // Handle Local Domain testing with the --local command line - const char* local = "--local"; - ::wantLocalDomain = cmdOptionExists(argc, argv,local); - if (::wantLocalDomain) { - printf("Local Domain MODE!\n"); - nodeList->setDomainIPToLocalhost(); - } else { - const char* domainIP = getCmdOption(argc, argv, "--domain"); if (domainIP) { - NodeList::getInstance()->setDomainHostname(domainIP); + VoxelServer::setupDomainAndPort(domainIP, listenPort); } } - nodeList->linkedDataCreateCallback = &attachVoxelNodeDataToNode; - nodeList->startSilentNodeRemovalThread(); - - srand((unsigned)time(0)); - - const char* DISPLAY_VOXEL_STATS = "--displayVoxelStats"; - ::displayVoxelStats = cmdOptionExists(argc, argv, DISPLAY_VOXEL_STATS); - printf("displayVoxelStats=%s\n", debug::valueOf(::displayVoxelStats)); - - const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending"; - ::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)); - - // By default we will voxel persist, if you want to disable this, then pass in this parameter - const char* NO_VOXEL_PERSIST = "--NoVoxelPersist"; - if (cmdOptionExists(argc, argv, NO_VOXEL_PERSIST)) { - ::wantVoxelPersist = false; - } - printf("wantVoxelPersist=%s\n", debug::valueOf(::wantVoxelPersist)); - - // if we want Voxel Persistence, load the local file now... - bool persistantFileRead = false; - if (::wantVoxelPersist) { - - // Check to see if the user passed in a command line option for setting packet send rate - const char* VOXELS_PERSIST_FILENAME = "--voxelsPersistFilename"; - const char* voxelsPersistFilenameParameter = getCmdOption(argc, argv, VOXELS_PERSIST_FILENAME); - if (voxelsPersistFilenameParameter) { - strcpy(voxelPersistFilename, voxelsPersistFilenameParameter); - } else { - strcpy(voxelPersistFilename, ::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); - } - - printf("loading voxels from file: %s...\n", voxelPersistFilename); - - persistantFileRead = ::serverTree.readFromSVOFile(::voxelPersistFilename); - if (persistantFileRead) { - PerformanceWarning warn(::shouldShowAnimationDebug, - "persistVoxelsWhenDirty() - reaverageVoxelColors()", ::shouldShowAnimationDebug); - - // after done inserting all these voxels, then reaverage colors - serverTree.reaverageVoxelColors(serverTree.rootNode); - printf("Voxels reAveraged\n"); - } - - ::serverTree.clearDirtyBit(); // the tree is clean since we just loaded it - printf("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead)); - unsigned long nodeCount = ::serverTree.rootNode->getSubTreeNodeCount(); - unsigned long internalNodeCount = ::serverTree.rootNode->getSubTreeInternalNodeCount(); - unsigned long leafNodeCount = ::serverTree.rootNode->getSubTreeLeafNodeCount(); - printf("Nodes after loading scene %lu nodes %lu internal %lu leaves\n", nodeCount, internalNodeCount, leafNodeCount); - - // now set up VoxelPersistThread - ::voxelPersistThread = new VoxelPersistThread(&::serverTree, ::voxelPersistFilename); - if (::voxelPersistThread) { - ::voxelPersistThread->initialize(true); - } - } - - // Check to see if the user passed in a command line option for loading an old style local - // Voxel File. If so, load it now. This is not the same as a voxel persist file - const char* INPUT_FILE = "-i"; - const char* voxelsFilename = getCmdOption(argc, argv, INPUT_FILE); - if (voxelsFilename) { - serverTree.readFromSVOFile(voxelsFilename); - } - - // Check to see if the user passed in a command line option for setting packet send rate - const char* PACKETS_PER_SECOND = "--packetsPerSecond"; - const char* packetsPerSecond = getCmdOption(argc, argv, PACKETS_PER_SECOND); - if (packetsPerSecond) { - PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/INTERVALS_PER_SECOND; - if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) { - PACKETS_PER_CLIENT_PER_INTERVAL = 1; - } - printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL); - } - - // for now, initialize the environments with fixed values - environmentData[1].setID(1); - environmentData[1].setGravity(1.0f); - environmentData[1].setAtmosphereCenter(glm::vec3(0.5, 0.5, (0.25 - 0.06125)) * (float)TREE_SCALE); - environmentData[1].setAtmosphereInnerRadius(0.030625f * TREE_SCALE); - environmentData[1].setAtmosphereOuterRadius(0.030625f * TREE_SCALE * 1.05f); - environmentData[2].setID(2); - environmentData[2].setGravity(1.0f); - environmentData[2].setAtmosphereCenter(glm::vec3(0.5f, 0.5f, 0.5f) * (float)TREE_SCALE); - environmentData[2].setAtmosphereInnerRadius(0.1875f * TREE_SCALE); - environmentData[2].setAtmosphereOuterRadius(0.1875f * TREE_SCALE * 1.05f); - environmentData[2].setScatteringWavelengths(glm::vec3(0.475f, 0.570f, 0.650f)); // swaps red and blue - - sockaddr senderAddress; - - unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE]; - ssize_t packetLength; - - timeval lastDomainServerCheckIn = {}; - - // set up our jurisdiction broadcaster... - ::jurisdictionSender = new JurisdictionSender(::jurisdiction); - if (::jurisdictionSender) { - ::jurisdictionSender->initialize(true); - } - - // set up our VoxelServerPacketProcessor - ::voxelServerPacketProcessor = new VoxelServerPacketProcessor(); - if (::voxelServerPacketProcessor) { - ::voxelServerPacketProcessor->initialize(true); - } - - // loop to send to nodes requesting data - while (true) { - - // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed - if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { - gettimeofday(&lastDomainServerCheckIn, NULL); - NodeList::getInstance()->sendDomainServerCheckIn(); - } - - if (nodeList->getNodeSocket()->receive(&senderAddress, packetData, &packetLength) && - packetVersionMatch(packetData)) { - - int numBytesPacketHeader = numBytesForPacketHeader(packetData); - - if (packetData[0] == PACKET_TYPE_HEAD_DATA) { - // If we got a PACKET_TYPE_HEAD_DATA, then we're talking to an NODE_TYPE_AVATAR, and we - // need to make sure we have it in our nodeList. - uint16_t nodeID = 0; - unpackNodeId(packetData + numBytesPacketHeader, &nodeID); - Node* node = NodeList::getInstance()->addOrUpdateNode(&senderAddress, - &senderAddress, - NODE_TYPE_AGENT, - nodeID); - - NodeList::getInstance()->updateNodeWithData(node, packetData, packetLength); - } else if (packetData[0] == PACKET_TYPE_PING) { - // If the packet is a ping, let processNodeData handle it. - NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); - } else if (packetData[0] == PACKET_TYPE_DOMAIN) { - NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); - } else if (packetData[0] == PACKET_TYPE_VOXEL_JURISDICTION_REQUEST) { - if (::jurisdictionSender) { - ::jurisdictionSender->queueReceivedPacket(senderAddress, packetData, packetLength); - } - } else if (::voxelServerPacketProcessor) { - ::voxelServerPacketProcessor->queueReceivedPacket(senderAddress, packetData, packetLength); - } else { - printf("unknown packet ignored... packetData[0]=%c\n", packetData[0]); - } - } - } - - if (::jurisdiction) { - delete ::jurisdiction; - } - - if (::jurisdictionSender) { - ::jurisdictionSender->terminate(); - delete ::jurisdictionSender; - } - - if (::voxelServerPacketProcessor) { - ::voxelServerPacketProcessor->terminate(); - delete ::voxelServerPacketProcessor; - } - - if (::voxelPersistThread) { - ::voxelPersistThread->terminate(); - delete ::voxelPersistThread; - } - - // tell our NodeList we're done with notifications - nodeList->removeHook(&nodeWatcher); - - pthread_mutex_destroy(&::treeLock); - - return 0; + VoxelServer::setArguments(argc, const_cast<char**>(argv)); + VoxelServer::run(); }