From 6a9418203d4c10ccdc33e6ef1d9f38c2c2743bf8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 24 Oct 2013 13:27:57 -0700 Subject: [PATCH 1/6] revert additionl of new VOXEL_QUERY message --- domain-server/CMakeLists.txt | 9 +- interface/src/Application.cpp | 59 ++++-- interface/src/Application.h | 6 +- libraries/avatars/src/AvatarData.cpp | 195 +----------------- libraries/avatars/src/AvatarData.h | 84 -------- libraries/avatars/src/HandData.cpp | 1 + libraries/shared/CMakeLists.txt | 9 +- libraries/shared/src/PacketHeaders.cpp | 2 +- libraries/shared/src/PacketHeaders.h | 17 +- libraries/shared/src/SharedUtil.cpp | 146 +++++++++++++ libraries/shared/src/SharedUtil.h | 38 ++++ .../src/VoxelNodeData.cpp | 2 +- .../voxel-server-library/src/VoxelNodeData.h | 4 +- .../src/VoxelSendThread.cpp | 11 +- .../voxel-server-library/src/VoxelServer.cpp | 4 +- libraries/voxels/src/VoxelConstants.h | 1 + 16 files changed, 274 insertions(+), 314 deletions(-) diff --git a/domain-server/CMakeLists.txt b/domain-server/CMakeLists.txt index 35f7bcc8d6..8a1a6a26dd 100644 --- a/domain-server/CMakeLists.txt +++ b/domain-server/CMakeLists.txt @@ -1,9 +1,16 @@ cmake_minimum_required(VERSION 2.8) +set(TARGET_NAME domain-server) + set(ROOT_DIR ..) set(MACRO_DIR ${ROOT_DIR}/cmake/macros) -set(TARGET_NAME domain-server) +# setup for find modules +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/") + +# set up the external glm library +include(${MACRO_DIR}/IncludeGLM.cmake) +include_glm(${TARGET_NAME} ${ROOT_DIR}) include(${MACRO_DIR}/SetupHifiProject.cmake) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8284477658..45c4a2aff4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2301,21 +2301,6 @@ void Application::updateAvatar(float deltaTime) { _myAvatar.getHead().setAudioLoudness(_audio.getLastInputLoudness()); #endif - // Update Avatar with latest camera and view frustum data... - // NOTE: we get this from the view frustum, to make it simpler, since the - // loadViewFrumstum() method will get the correct details from the camera - // We could optimize this to not actually load the viewFrustum, since we don't - // actually need to calculate the view frustum planes to send these details - // to the server. - loadViewFrustum(_myCamera, _viewFrustum); - _myAvatar.setCameraPosition(_viewFrustum.getPosition()); - _myAvatar.setCameraOrientation(_viewFrustum.getOrientation()); - _myAvatar.setCameraFov(_viewFrustum.getFieldOfView()); - _myAvatar.setCameraAspectRatio(_viewFrustum.getAspectRatio()); - _myAvatar.setCameraNearClip(_viewFrustum.getNearClip()); - _myAvatar.setCameraFarClip(_viewFrustum.getFarClip()); - _myAvatar.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition()); - NodeList* nodeList = NodeList::getInstance(); // send head/hand data to the avatar mixer and voxel server @@ -2330,7 +2315,7 @@ void Application::updateAvatar(float deltaTime) { endOfBroadcastStringWrite += _myAvatar.getBroadcastData(endOfBroadcastStringWrite); - const char nodeTypesOfInterest[] = { NODE_TYPE_VOXEL_SERVER, NODE_TYPE_AVATAR_MIXER }; + const char nodeTypesOfInterest[] = { NODE_TYPE_AVATAR_MIXER }; controlledBroadcastToNodes(broadcastString, endOfBroadcastStringWrite - broadcastString, nodeTypesOfInterest, sizeof(nodeTypesOfInterest)); @@ -2339,6 +2324,48 @@ void Application::updateAvatar(float deltaTime) { if (shouldDo(AVATAR_URLS_SEND_INTERVAL, deltaTime)) { Avatar::sendAvatarURLsMessage(_myAvatar.getVoxels()->getVoxelURL()); } + + // Update _viewFrustum with latest camera and view frustum data... + // NOTE: we get this from the view frustum, to make it simpler, since the + // loadViewFrumstum() method will get the correct details from the camera + // We could optimize this to not actually load the viewFrustum, since we don't + // actually need to calculate the view frustum planes to send these details + // to the server. + loadViewFrustum(_myCamera, _viewFrustum); + + // Update my voxel servers with my current voxel query... + queryVoxels(); +} + +void Application::queryVoxels() { + // Need to update this to support multiple different servers... + + _voxelQuery.setCameraPosition(_viewFrustum.getPosition()); + _voxelQuery.setCameraOrientation(_viewFrustum.getOrientation()); + _voxelQuery.setCameraFov(_viewFrustum.getFieldOfView()); + _voxelQuery.setCameraAspectRatio(_viewFrustum.getAspectRatio()); + _voxelQuery.setCameraNearClip(_viewFrustum.getNearClip()); + _voxelQuery.setCameraFarClip(_viewFrustum.getFarClip()); + _voxelQuery.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition()); + + NodeList* nodeList = NodeList::getInstance(); + + // send head/hand data to the avatar mixer and voxel server + unsigned char voxelQueryPacket[MAX_PACKET_SIZE]; + unsigned char* endOfVoxelQueryPacket = voxelQueryPacket; + + endOfVoxelQueryPacket += populateTypeAndVersion(endOfVoxelQueryPacket, PACKET_TYPE_VOXEL_QUERY); + + QByteArray ownerUUID = nodeList->getOwnerUUID().toRfc4122(); + memcpy(endOfVoxelQueryPacket, ownerUUID.constData(), ownerUUID.size()); + endOfVoxelQueryPacket += ownerUUID.size(); + + endOfVoxelQueryPacket += _voxelQuery.getBroadcastData(endOfVoxelQueryPacket); + + const char nodeTypesOfInterest[] = { NODE_TYPE_VOXEL_SERVER }; + controlledBroadcastToNodes(voxelQueryPacket, endOfVoxelQueryPacket - voxelQueryPacket, + nodeTypesOfInterest, sizeof(nodeTypesOfInterest)); + } ///////////////////////////////////////////////////////////////////////////////////// diff --git a/interface/src/Application.h b/interface/src/Application.h index b4ad7f4bb2..6118bfb8b3 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -22,6 +22,7 @@ #include #include #include +#include #ifndef _WIN32 #include "Audio.h" @@ -218,6 +219,7 @@ private: void renderFollowIndicator(); void updateAvatar(float deltaTime); void updateAvatars(float deltaTime, glm::vec3 mouseRayOrigin, glm::vec3 mouseRayDirection); + void queryVoxels(); void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum); void displayOculus(Camera& whichCamera); @@ -280,9 +282,11 @@ private: QByteArray _voxelsFilename; bool _wantToKillLocalVoxels; - ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. + ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. Oscilloscope _audioScope; + + VoxelQuery _voxelQuery; // NodeData derived class for querying voxels from voxel server MyAvatar _myAvatar; // The rendered avatar of oneself Profile _profile; // The data-server linked profile for this user diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index e9a4034b09..670cbd7487 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -32,17 +32,7 @@ AvatarData::AvatarData(Node* owningNode) : _newScale(1.0f), _leaderUUID(), _handState(0), - _cameraPosition(0,0,0), - _cameraOrientation(), - _cameraFov(0.0f), - _cameraAspectRatio(0.0f), - _cameraNearClip(0.0f), - _cameraFarClip(0.0f), _keyState(NO_KEY_DOWN), - _wantColor(true), - _wantDelta(true), - _wantLowResMoving(true), - _wantOcclusionCulling(true), _headData(NULL), _handData(NULL) { @@ -116,17 +106,6 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { memcpy(destinationBuffer, &_headData->_audioLoudness, sizeof(float)); destinationBuffer += sizeof(float); - // camera details - memcpy(destinationBuffer, &_cameraPosition, sizeof(_cameraPosition)); - destinationBuffer += sizeof(_cameraPosition); - destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _cameraOrientation); - destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _cameraFov); - destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _cameraAspectRatio); - destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraNearClip); - destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraFarClip); - memcpy(destinationBuffer, &_cameraEyeOffsetPosition, sizeof(_cameraEyeOffsetPosition)); - destinationBuffer += sizeof(_cameraEyeOffsetPosition); - // chat message *destinationBuffer++ = _chatMessage.size(); memcpy(destinationBuffer, _chatMessage.data(), _chatMessage.size() * sizeof(char)); @@ -134,10 +113,6 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { // bitMask of less than byte wide items unsigned char bitItems = 0; - if (_wantLowResMoving) { setAtBit(bitItems, WANT_LOW_RES_MOVING_BIT); } - if (_wantColor) { setAtBit(bitItems, WANT_COLOR_AT_BIT); } - if (_wantDelta) { setAtBit(bitItems, WANT_DELTA_AT_BIT); } - if (_wantOcclusionCulling) { setAtBit(bitItems, WANT_OCCLUSION_CULLING_BIT); } // key state setSemiNibbleAt(bitItems,KEY_STATE_START_BIT,_keyState); @@ -182,7 +157,7 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { *destinationBuffer++ = (unsigned char)it->jointID; destinationBuffer += packOrientationQuatToBytes(destinationBuffer, it->rotation); } - + return destinationBuffer - bufferStart; } @@ -259,17 +234,6 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { memcpy(&_headData->_audioLoudness, sourceBuffer, sizeof(float)); sourceBuffer += sizeof(float); - // camera details - memcpy(&_cameraPosition, sourceBuffer, sizeof(_cameraPosition)); - sourceBuffer += sizeof(_cameraPosition); - sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, _cameraOrientation); - sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_cameraFov); - sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer,_cameraAspectRatio); - sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraNearClip); - sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraFarClip); - memcpy(&_cameraEyeOffsetPosition, sourceBuffer, sizeof(_cameraEyeOffsetPosition)); - sourceBuffer += sizeof(_cameraEyeOffsetPosition); - // the rest is a chat message int chatMessageSize = *sourceBuffer++; _chatMessage = string((char*)sourceBuffer, chatMessageSize); @@ -278,10 +242,6 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { // voxel sending features... unsigned char bitItems = 0; bitItems = (unsigned char)*sourceBuffer++; - _wantLowResMoving = oneAtBit(bitItems, WANT_LOW_RES_MOVING_BIT); - _wantColor = oneAtBit(bitItems, WANT_COLOR_AT_BIT); - _wantDelta = oneAtBit(bitItems, WANT_DELTA_AT_BIT); - _wantOcclusionCulling = oneAtBit(bitItems, WANT_OCCLUSION_CULLING_BIT); // key state, stored as a semi-nibble in the bitItems _keyState = (KeyState)getSemiNibbleAt(bitItems,KEY_STATE_START_BIT); @@ -330,157 +290,6 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, it->rotation); } } - + return sourceBuffer - startPosition; } - -glm::vec3 AvatarData::calculateCameraDirection() const { - glm::vec3 direction = glm::vec3(_cameraOrientation * glm::vec4(IDENTITY_FRONT, 0.0f)); - return direction; -} - - -// Allows sending of fixed-point numbers: radix 1 makes 15.1 number, radix 8 makes 8.8 number, etc -int packFloatScalarToSignedTwoByteFixed(unsigned char* buffer, float scalar, int radix) { - int16_t outVal = (int16_t)(scalar * (float)(1 << radix)); - memcpy(buffer, &outVal, sizeof(uint16_t)); - return sizeof(uint16_t); -} - -int unpackFloatScalarFromSignedTwoByteFixed(int16_t* byteFixedPointer, float* destinationPointer, int radix) { - *destinationPointer = *byteFixedPointer / (float)(1 << radix); - return sizeof(int16_t); -} - -int packFloatVec3ToSignedTwoByteFixed(unsigned char* destBuffer, const glm::vec3& srcVector, int radix) { - const unsigned char* startPosition = destBuffer; - destBuffer += packFloatScalarToSignedTwoByteFixed(destBuffer, srcVector.x, radix); - destBuffer += packFloatScalarToSignedTwoByteFixed(destBuffer, srcVector.y, radix); - destBuffer += packFloatScalarToSignedTwoByteFixed(destBuffer, srcVector.z, radix); - return destBuffer - startPosition; -} - -int unpackFloatVec3FromSignedTwoByteFixed(unsigned char* sourceBuffer, glm::vec3& destination, int radix) { - const unsigned char* startPosition = sourceBuffer; - sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(destination.x), radix); - sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(destination.y), radix); - sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(destination.z), radix); - return sourceBuffer - startPosition; -} - - -int packFloatAngleToTwoByte(unsigned char* buffer, float angle) { - const float ANGLE_CONVERSION_RATIO = (std::numeric_limits::max() / 360.0); - - uint16_t angleHolder = floorf((angle + 180) * ANGLE_CONVERSION_RATIO); - memcpy(buffer, &angleHolder, sizeof(uint16_t)); - - return sizeof(uint16_t); -} - -int unpackFloatAngleFromTwoByte(uint16_t* byteAnglePointer, float* destinationPointer) { - *destinationPointer = (*byteAnglePointer / (float) std::numeric_limits::max()) * 360.0 - 180; - return sizeof(uint16_t); -} - -int packOrientationQuatToBytes(unsigned char* buffer, const glm::quat& quatInput) { - const float QUAT_PART_CONVERSION_RATIO = (std::numeric_limits::max() / 2.0); - uint16_t quatParts[4]; - quatParts[0] = floorf((quatInput.x + 1.0) * QUAT_PART_CONVERSION_RATIO); - quatParts[1] = floorf((quatInput.y + 1.0) * QUAT_PART_CONVERSION_RATIO); - quatParts[2] = floorf((quatInput.z + 1.0) * QUAT_PART_CONVERSION_RATIO); - quatParts[3] = floorf((quatInput.w + 1.0) * QUAT_PART_CONVERSION_RATIO); - - memcpy(buffer, &quatParts, sizeof(quatParts)); - return sizeof(quatParts); -} - -int unpackOrientationQuatFromBytes(unsigned char* buffer, glm::quat& quatOutput) { - uint16_t quatParts[4]; - memcpy(&quatParts, buffer, sizeof(quatParts)); - - quatOutput.x = ((quatParts[0] / (float) std::numeric_limits::max()) * 2.0) - 1.0; - quatOutput.y = ((quatParts[1] / (float) std::numeric_limits::max()) * 2.0) - 1.0; - quatOutput.z = ((quatParts[2] / (float) std::numeric_limits::max()) * 2.0) - 1.0; - quatOutput.w = ((quatParts[3] / (float) std::numeric_limits::max()) * 2.0) - 1.0; - - return sizeof(quatParts); -} - -float SMALL_LIMIT = 10.0; -float LARGE_LIMIT = 1000.0; - -int packFloatRatioToTwoByte(unsigned char* buffer, float ratio) { - // if the ratio is less than 10, then encode it as a positive number scaled from 0 to int16::max() - int16_t ratioHolder; - - if (ratio < SMALL_LIMIT) { - const float SMALL_RATIO_CONVERSION_RATIO = (std::numeric_limits::max() / SMALL_LIMIT); - ratioHolder = floorf(ratio * SMALL_RATIO_CONVERSION_RATIO); - } else { - const float LARGE_RATIO_CONVERSION_RATIO = std::numeric_limits::min() / LARGE_LIMIT; - ratioHolder = floorf((std::min(ratio,LARGE_LIMIT) - SMALL_LIMIT) * LARGE_RATIO_CONVERSION_RATIO); - } - memcpy(buffer, &ratioHolder, sizeof(ratioHolder)); - return sizeof(ratioHolder); -} - -int unpackFloatRatioFromTwoByte(unsigned char* buffer, float& ratio) { - int16_t ratioHolder; - memcpy(&ratioHolder, buffer, sizeof(ratioHolder)); - - // If it's positive, than the original ratio was less than SMALL_LIMIT - if (ratioHolder > 0) { - ratio = (ratioHolder / (float) std::numeric_limits::max()) * SMALL_LIMIT; - } else { - // If it's negative, than the original ratio was between SMALL_LIMIT and LARGE_LIMIT - ratio = ((ratioHolder / (float) std::numeric_limits::min()) * LARGE_LIMIT) + SMALL_LIMIT; - } - return sizeof(ratioHolder); -} - -int packClipValueToTwoByte(unsigned char* buffer, float clipValue) { - // Clip values must be less than max signed 16bit integers - assert(clipValue < std::numeric_limits::max()); - int16_t holder; - - // if the clip is less than 10, then encode it as a positive number scaled from 0 to int16::max() - if (clipValue < SMALL_LIMIT) { - const float SMALL_RATIO_CONVERSION_RATIO = (std::numeric_limits::max() / SMALL_LIMIT); - holder = floorf(clipValue * SMALL_RATIO_CONVERSION_RATIO); - } else { - // otherwise we store it as a negative integer - holder = -1 * floorf(clipValue); - } - memcpy(buffer, &holder, sizeof(holder)); - return sizeof(holder); -} - -int unpackClipValueFromTwoByte(unsigned char* buffer, float& clipValue) { - int16_t holder; - memcpy(&holder, buffer, sizeof(holder)); - - // If it's positive, than the original clipValue was less than SMALL_LIMIT - if (holder > 0) { - clipValue = (holder / (float) std::numeric_limits::max()) * SMALL_LIMIT; - } else { - // If it's negative, than the original holder can be found as the opposite sign of holder - clipValue = -1.0f * holder; - } - return sizeof(holder); -} - -int packFloatToByte(unsigned char* buffer, float value, float scaleBy) { - unsigned char holder; - const float CONVERSION_RATIO = (255 / scaleBy); - holder = floorf(value * CONVERSION_RATIO); - memcpy(buffer, &holder, sizeof(holder)); - return sizeof(holder); -} - -int unpackFloatFromByte(unsigned char* buffer, float& value, float scaleBy) { - unsigned char holder; - memcpy(&holder, buffer, sizeof(holder)); - value = ((float)holder / (float) 255) * scaleBy; - return sizeof(holder); -} diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index c621fbbe63..2f9ca6483d 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -27,12 +27,8 @@ #include "HandData.h" // First bitset -const int WANT_LOW_RES_MOVING_BIT = 0; -const int WANT_COLOR_AT_BIT = 1; -const int WANT_DELTA_AT_BIT = 2; const int KEY_STATE_START_BIT = 3; // 4th and 5th bits const int HAND_STATE_START_BIT = 5; // 6th and 7th bits -const int WANT_OCCLUSION_CULLING_BIT = 7; // 8th bit // Second bitset const int IS_FACESHIFT_CONNECTED = 0; @@ -85,26 +81,6 @@ public: void setHandState(char s) { _handState = s; } char getHandState() const { return _handState; } - // getters for camera details - const glm::vec3& getCameraPosition() const { return _cameraPosition; } - const glm::quat& getCameraOrientation() const { return _cameraOrientation; } - float getCameraFov() const { return _cameraFov; } - float getCameraAspectRatio() const { return _cameraAspectRatio; } - float getCameraNearClip() const { return _cameraNearClip; } - float getCameraFarClip() const { return _cameraFarClip; } - const glm::vec3& getCameraEyeOffsetPosition() const { return _cameraEyeOffsetPosition; } - - glm::vec3 calculateCameraDirection() const; - - // setters for camera details - void setCameraPosition(const glm::vec3& position) { _cameraPosition = position; } - void setCameraOrientation(const glm::quat& orientation) { _cameraOrientation = orientation; } - void setCameraFov(float fov) { _cameraFov = fov; } - void setCameraAspectRatio(float aspectRatio) { _cameraAspectRatio = aspectRatio; } - void setCameraNearClip(float nearClip) { _cameraNearClip = nearClip; } - void setCameraFarClip(float farClip) { _cameraFarClip = farClip; } - void setCameraEyeOffsetPosition(const glm::vec3& eyeOffsetPosition) { _cameraEyeOffsetPosition = eyeOffsetPosition; } - // key state void setKeyState(KeyState s) { _keyState = s; } KeyState keyState() const { return _keyState; } @@ -115,22 +91,11 @@ public: const std::string& setChatMessage() const { return _chatMessage; } QString getQStringChatMessage() { return QString(_chatMessage.data()); } - // related to Voxel Sending strategies - bool getWantColor() const { return _wantColor; } - bool getWantDelta() const { return _wantDelta; } - bool getWantLowResMoving() const { return _wantLowResMoving; } - bool getWantOcclusionCulling() const { return _wantOcclusionCulling; } const QUuid& getLeaderUUID() const { return _leaderUUID; } void setHeadData(HeadData* headData) { _headData = headData; } void setHandData(HandData* handData) { _handData = handData; } -public slots: - void setWantLowResMoving(bool wantLowResMoving) { _wantLowResMoving = wantLowResMoving; } - void setWantColor(bool wantColor) { _wantColor = wantColor; } - void setWantDelta(bool wantDelta) { _wantDelta = wantDelta; } - void setWantOcclusionCulling(bool wantOcclusionCulling) { _wantOcclusionCulling = wantOcclusionCulling; } - protected: QUuid _uuid; @@ -151,27 +116,12 @@ protected: // Hand state (are we grabbing something or not) char _handState; - // camera details for the avatar - glm::vec3 _cameraPosition; - glm::quat _cameraOrientation; - float _cameraFov; - float _cameraAspectRatio; - float _cameraNearClip; - float _cameraFarClip; - glm::vec3 _cameraEyeOffsetPosition; - // key state KeyState _keyState; // chat message std::string _chatMessage; - // voxel server sending items - bool _wantColor; - bool _wantDelta; - bool _wantLowResMoving; - bool _wantOcclusionCulling; - std::vector _joints; HeadData* _headData; @@ -190,38 +140,4 @@ public: glm::quat rotation; }; -// These pack/unpack functions are designed to start specific known types in as efficient a manner -// as possible. Taking advantage of the known characteristics of the semantic types. - -// Angles are known to be between 0 and 360deg, this allows us to encode in 16bits with great accuracy -int packFloatAngleToTwoByte(unsigned char* buffer, float angle); -int unpackFloatAngleFromTwoByte(uint16_t* byteAnglePointer, float* destinationPointer); - -// Orientation Quats are known to have 4 normalized components be between -1.0 and 1.0 -// this allows us to encode each component in 16bits with great accuracy -int packOrientationQuatToBytes(unsigned char* buffer, const glm::quat& quatInput); -int unpackOrientationQuatFromBytes(unsigned char* buffer, glm::quat& quatOutput); - -// Ratios need the be highly accurate when less than 10, but not very accurate above 10, and they -// are never greater than 1000 to 1, this allows us to encode each component in 16bits -int packFloatRatioToTwoByte(unsigned char* buffer, float ratio); -int unpackFloatRatioFromTwoByte(unsigned char* buffer, float& ratio); - -// Near/Far Clip values need the be highly accurate when less than 10, but only integer accuracy above 10 and -// they are never greater than 16,000, this allows us to encode each component in 16bits -int packClipValueToTwoByte(unsigned char* buffer, float clipValue); -int unpackClipValueFromTwoByte(unsigned char* buffer, float& clipValue); - -// Positive floats that don't need to be very precise -int packFloatToByte(unsigned char* buffer, float value, float scaleBy); -int unpackFloatFromByte(unsigned char* buffer, float& value, float scaleBy); - -// Allows sending of fixed-point numbers: radix 1 makes 15.1 number, radix 8 makes 8.8 number, etc -int packFloatScalarToSignedTwoByteFixed(unsigned char* buffer, float scalar, int radix); -int unpackFloatScalarFromSignedTwoByteFixed(int16_t* byteFixedPointer, float* destinationPointer, int radix); - -// A convenience for sending vec3's as fixed-poimt floats -int packFloatVec3ToSignedTwoByteFixed(unsigned char* destBuffer, const glm::vec3& srcVector, int radix); -int unpackFloatVec3FromSignedTwoByteFixed(unsigned char* sourceBuffer, glm::vec3& destination, int radix); - #endif /* defined(__hifi__AvatarData__) */ diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index e00854e2b5..f00dbff327 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -8,6 +8,7 @@ #include "HandData.h" #include "AvatarData.h" +#include // Glove flags #define GLOVE_FLAG_RAVE 0x01 diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index d9bfc769d1..8c05b1ff8f 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -13,6 +13,11 @@ setup_hifi_library(${TARGET_NAME}) qt5_use_modules(${TARGET_NAME} Network) +# include GLM +include(${MACRO_DIR}/IncludeGLM.cmake) +include_glm(${TARGET_NAME} ${ROOT_DIR}) + + set(EXTERNAL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external) if (WIN32) @@ -29,7 +34,3 @@ if (UNIX AND NOT APPLE) find_package(Threads REQUIRED) target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT}) endif (UNIX AND NOT APPLE) - -# include GLM -include(${MACRO_DIR}/IncludeGLM.cmake) -include_glm(${TARGET_NAME} ${ROOT_DIR}) diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 134a811c6b..70544f536b 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -20,7 +20,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) { return 2; case PACKET_TYPE_HEAD_DATA: - return 10; + return 11; case PACKET_TYPE_AVATAR_URLS: return 2; diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index 2c4172ee55..a9f320bafd 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -24,11 +24,6 @@ const PACKET_TYPE PACKET_TYPE_INJECT_AUDIO = 'I'; const PACKET_TYPE PACKET_TYPE_MIXED_AUDIO = 'A'; const PACKET_TYPE PACKET_TYPE_MICROPHONE_AUDIO_NO_ECHO = 'M'; const PACKET_TYPE PACKET_TYPE_MICROPHONE_AUDIO_WITH_ECHO = 'm'; -const PACKET_TYPE PACKET_TYPE_SET_VOXEL = 'S'; -const PACKET_TYPE PACKET_TYPE_SET_VOXEL_DESTRUCTIVE = 'O'; -const PACKET_TYPE PACKET_TYPE_ERASE_VOXEL = 'E'; -const PACKET_TYPE PACKET_TYPE_VOXEL_DATA = 'V'; -const PACKET_TYPE PACKET_TYPE_VOXEL_DATA_MONOCHROME = 'v'; const PACKET_TYPE PACKET_TYPE_BULK_AVATAR_DATA = 'X'; const PACKET_TYPE PACKET_TYPE_AVATAR_URLS = 'U'; const PACKET_TYPE PACKET_TYPE_AVATAR_FACE_VIDEO = 'F'; @@ -39,13 +34,19 @@ const PACKET_TYPE PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY = 'C'; const PACKET_TYPE PACKET_TYPE_REQUEST_ASSIGNMENT = 'r'; const PACKET_TYPE PACKET_TYPE_CREATE_ASSIGNMENT = 's'; const PACKET_TYPE PACKET_TYPE_DEPLOY_ASSIGNMENT = 'd'; -const PACKET_TYPE PACKET_TYPE_VOXEL_STATS = '#'; -const PACKET_TYPE PACKET_TYPE_VOXEL_JURISDICTION = 'J'; -const PACKET_TYPE PACKET_TYPE_VOXEL_JURISDICTION_REQUEST = 'j'; const PACKET_TYPE PACKET_TYPE_DATA_SERVER_PUT = 'p'; const PACKET_TYPE PACKET_TYPE_DATA_SERVER_GET = 'g'; const PACKET_TYPE PACKET_TYPE_DATA_SERVER_SEND = 'u'; const PACKET_TYPE PACKET_TYPE_DATA_SERVER_CONFIRM = 'c'; +const PACKET_TYPE PACKET_TYPE_VOXEL_QUERY = 'q'; +const PACKET_TYPE PACKET_TYPE_VOXEL_DATA = 'V'; +const PACKET_TYPE PACKET_TYPE_VOXEL_DATA_MONOCHROME = 'v'; +const PACKET_TYPE PACKET_TYPE_VOXEL_STATS = '#'; +const PACKET_TYPE PACKET_TYPE_VOXEL_JURISDICTION = 'J'; +const PACKET_TYPE PACKET_TYPE_VOXEL_JURISDICTION_REQUEST = 'j'; +const PACKET_TYPE PACKET_TYPE_SET_VOXEL = 'S'; +const PACKET_TYPE PACKET_TYPE_SET_VOXEL_DESTRUCTIVE = 'O'; +const PACKET_TYPE PACKET_TYPE_ERASE_VOXEL = 'E'; typedef char PACKET_VERSION; diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 3d4759c98a..0b8af8b48b 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -535,3 +535,149 @@ int removeFromSortedArrays(void* value, void** valueArray, float* keyArray, int* } return -1; // error case } + +// Allows sending of fixed-point numbers: radix 1 makes 15.1 number, radix 8 makes 8.8 number, etc +int packFloatScalarToSignedTwoByteFixed(unsigned char* buffer, float scalar, int radix) { + int16_t outVal = (int16_t)(scalar * (float)(1 << radix)); + memcpy(buffer, &outVal, sizeof(uint16_t)); + return sizeof(uint16_t); +} + +int unpackFloatScalarFromSignedTwoByteFixed(int16_t* byteFixedPointer, float* destinationPointer, int radix) { + *destinationPointer = *byteFixedPointer / (float)(1 << radix); + return sizeof(int16_t); +} + +int packFloatVec3ToSignedTwoByteFixed(unsigned char* destBuffer, const glm::vec3& srcVector, int radix) { + const unsigned char* startPosition = destBuffer; + destBuffer += packFloatScalarToSignedTwoByteFixed(destBuffer, srcVector.x, radix); + destBuffer += packFloatScalarToSignedTwoByteFixed(destBuffer, srcVector.y, radix); + destBuffer += packFloatScalarToSignedTwoByteFixed(destBuffer, srcVector.z, radix); + return destBuffer - startPosition; +} + +int unpackFloatVec3FromSignedTwoByteFixed(unsigned char* sourceBuffer, glm::vec3& destination, int radix) { + const unsigned char* startPosition = sourceBuffer; + sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(destination.x), radix); + sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(destination.y), radix); + sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(destination.z), radix); + return sourceBuffer - startPosition; +} + + +int packFloatAngleToTwoByte(unsigned char* buffer, float angle) { + const float ANGLE_CONVERSION_RATIO = (std::numeric_limits::max() / 360.0); + + uint16_t angleHolder = floorf((angle + 180) * ANGLE_CONVERSION_RATIO); + memcpy(buffer, &angleHolder, sizeof(uint16_t)); + + return sizeof(uint16_t); +} + +int unpackFloatAngleFromTwoByte(uint16_t* byteAnglePointer, float* destinationPointer) { + *destinationPointer = (*byteAnglePointer / (float) std::numeric_limits::max()) * 360.0 - 180; + return sizeof(uint16_t); +} + +int packOrientationQuatToBytes(unsigned char* buffer, const glm::quat& quatInput) { + const float QUAT_PART_CONVERSION_RATIO = (std::numeric_limits::max() / 2.0); + uint16_t quatParts[4]; + quatParts[0] = floorf((quatInput.x + 1.0) * QUAT_PART_CONVERSION_RATIO); + quatParts[1] = floorf((quatInput.y + 1.0) * QUAT_PART_CONVERSION_RATIO); + quatParts[2] = floorf((quatInput.z + 1.0) * QUAT_PART_CONVERSION_RATIO); + quatParts[3] = floorf((quatInput.w + 1.0) * QUAT_PART_CONVERSION_RATIO); + + memcpy(buffer, &quatParts, sizeof(quatParts)); + return sizeof(quatParts); +} + +int unpackOrientationQuatFromBytes(unsigned char* buffer, glm::quat& quatOutput) { + uint16_t quatParts[4]; + memcpy(&quatParts, buffer, sizeof(quatParts)); + + quatOutput.x = ((quatParts[0] / (float) std::numeric_limits::max()) * 2.0) - 1.0; + quatOutput.y = ((quatParts[1] / (float) std::numeric_limits::max()) * 2.0) - 1.0; + quatOutput.z = ((quatParts[2] / (float) std::numeric_limits::max()) * 2.0) - 1.0; + quatOutput.w = ((quatParts[3] / (float) std::numeric_limits::max()) * 2.0) - 1.0; + + return sizeof(quatParts); +} + +float SMALL_LIMIT = 10.0; +float LARGE_LIMIT = 1000.0; + +int packFloatRatioToTwoByte(unsigned char* buffer, float ratio) { + // if the ratio is less than 10, then encode it as a positive number scaled from 0 to int16::max() + int16_t ratioHolder; + + if (ratio < SMALL_LIMIT) { + const float SMALL_RATIO_CONVERSION_RATIO = (std::numeric_limits::max() / SMALL_LIMIT); + ratioHolder = floorf(ratio * SMALL_RATIO_CONVERSION_RATIO); + } else { + const float LARGE_RATIO_CONVERSION_RATIO = std::numeric_limits::min() / LARGE_LIMIT; + ratioHolder = floorf((std::min(ratio,LARGE_LIMIT) - SMALL_LIMIT) * LARGE_RATIO_CONVERSION_RATIO); + } + memcpy(buffer, &ratioHolder, sizeof(ratioHolder)); + return sizeof(ratioHolder); +} + +int unpackFloatRatioFromTwoByte(unsigned char* buffer, float& ratio) { + int16_t ratioHolder; + memcpy(&ratioHolder, buffer, sizeof(ratioHolder)); + + // If it's positive, than the original ratio was less than SMALL_LIMIT + if (ratioHolder > 0) { + ratio = (ratioHolder / (float) std::numeric_limits::max()) * SMALL_LIMIT; + } else { + // If it's negative, than the original ratio was between SMALL_LIMIT and LARGE_LIMIT + ratio = ((ratioHolder / (float) std::numeric_limits::min()) * LARGE_LIMIT) + SMALL_LIMIT; + } + return sizeof(ratioHolder); +} + +int packClipValueToTwoByte(unsigned char* buffer, float clipValue) { + // Clip values must be less than max signed 16bit integers + assert(clipValue < std::numeric_limits::max()); + int16_t holder; + + // if the clip is less than 10, then encode it as a positive number scaled from 0 to int16::max() + if (clipValue < SMALL_LIMIT) { + const float SMALL_RATIO_CONVERSION_RATIO = (std::numeric_limits::max() / SMALL_LIMIT); + holder = floorf(clipValue * SMALL_RATIO_CONVERSION_RATIO); + } else { + // otherwise we store it as a negative integer + holder = -1 * floorf(clipValue); + } + memcpy(buffer, &holder, sizeof(holder)); + return sizeof(holder); +} + +int unpackClipValueFromTwoByte(unsigned char* buffer, float& clipValue) { + int16_t holder; + memcpy(&holder, buffer, sizeof(holder)); + + // If it's positive, than the original clipValue was less than SMALL_LIMIT + if (holder > 0) { + clipValue = (holder / (float) std::numeric_limits::max()) * SMALL_LIMIT; + } else { + // If it's negative, than the original holder can be found as the opposite sign of holder + clipValue = -1.0f * holder; + } + return sizeof(holder); +} + +int packFloatToByte(unsigned char* buffer, float value, float scaleBy) { + unsigned char holder; + const float CONVERSION_RATIO = (255 / scaleBy); + holder = floorf(value * CONVERSION_RATIO); + memcpy(buffer, &holder, sizeof(holder)); + return sizeof(holder); +} + +int unpackFloatFromByte(unsigned char* buffer, float& value, float scaleBy) { + unsigned char holder; + memcpy(&holder, buffer, sizeof(holder)); + value = ((float)holder / (float) 255) * scaleBy; + return sizeof(holder); +} + diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index ece63d4737..8f04ee15d5 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -13,6 +13,9 @@ #include #include +#include +#include + #include #ifdef _WIN32 @@ -113,4 +116,39 @@ public: bool isBetween(int64_t value, int64_t max, int64_t min); + +// These pack/unpack functions are designed to start specific known types in as efficient a manner +// as possible. Taking advantage of the known characteristics of the semantic types. + +// Angles are known to be between 0 and 360deg, this allows us to encode in 16bits with great accuracy +int packFloatAngleToTwoByte(unsigned char* buffer, float angle); +int unpackFloatAngleFromTwoByte(uint16_t* byteAnglePointer, float* destinationPointer); + +// Orientation Quats are known to have 4 normalized components be between -1.0 and 1.0 +// this allows us to encode each component in 16bits with great accuracy +int packOrientationQuatToBytes(unsigned char* buffer, const glm::quat& quatInput); +int unpackOrientationQuatFromBytes(unsigned char* buffer, glm::quat& quatOutput); + +// Ratios need the be highly accurate when less than 10, but not very accurate above 10, and they +// are never greater than 1000 to 1, this allows us to encode each component in 16bits +int packFloatRatioToTwoByte(unsigned char* buffer, float ratio); +int unpackFloatRatioFromTwoByte(unsigned char* buffer, float& ratio); + +// Near/Far Clip values need the be highly accurate when less than 10, but only integer accuracy above 10 and +// they are never greater than 16,000, this allows us to encode each component in 16bits +int packClipValueToTwoByte(unsigned char* buffer, float clipValue); +int unpackClipValueFromTwoByte(unsigned char* buffer, float& clipValue); + +// Positive floats that don't need to be very precise +int packFloatToByte(unsigned char* buffer, float value, float scaleBy); +int unpackFloatFromByte(unsigned char* buffer, float& value, float scaleBy); + +// Allows sending of fixed-point numbers: radix 1 makes 15.1 number, radix 8 makes 8.8 number, etc +int packFloatScalarToSignedTwoByteFixed(unsigned char* buffer, float scalar, int radix); +int unpackFloatScalarFromSignedTwoByteFixed(int16_t* byteFixedPointer, float* destinationPointer, int radix); + +// A convenience for sending vec3's as fixed-poimt floats +int packFloatVec3ToSignedTwoByteFixed(unsigned char* destBuffer, const glm::vec3& srcVector, int radix); +int unpackFloatVec3FromSignedTwoByteFixed(unsigned char* sourceBuffer, glm::vec3& destination, int radix); + #endif /* defined(__hifi__SharedUtil__) */ diff --git a/libraries/voxel-server-library/src/VoxelNodeData.cpp b/libraries/voxel-server-library/src/VoxelNodeData.cpp index 1950c41790..741e33e07d 100644 --- a/libraries/voxel-server-library/src/VoxelNodeData.cpp +++ b/libraries/voxel-server-library/src/VoxelNodeData.cpp @@ -14,7 +14,7 @@ #include "VoxelSendThread.h" VoxelNodeData::VoxelNodeData(Node* owningNode) : - AvatarData(owningNode), + VoxelQuery(owningNode), _viewSent(false), _voxelPacketAvailableBytes(MAX_VOXEL_PACKET_SIZE), _maxSearchLevel(1), diff --git a/libraries/voxel-server-library/src/VoxelNodeData.h b/libraries/voxel-server-library/src/VoxelNodeData.h index 0a8412f8e8..4049cdda36 100644 --- a/libraries/voxel-server-library/src/VoxelNodeData.h +++ b/libraries/voxel-server-library/src/VoxelNodeData.h @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include @@ -21,7 +21,7 @@ class VoxelSendThread; class VoxelServer; -class VoxelNodeData : public AvatarData { +class VoxelNodeData : public VoxelQuery { public: VoxelNodeData(Node* owningNode); ~VoxelNodeData(); diff --git a/libraries/voxel-server-library/src/VoxelSendThread.cpp b/libraries/voxel-server-library/src/VoxelSendThread.cpp index 1966bc7952..bd78c507fd 100644 --- a/libraries/voxel-server-library/src/VoxelSendThread.cpp +++ b/libraries/voxel-server-library/src/VoxelSendThread.cpp @@ -219,7 +219,16 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no uint64_t start = usecTimestampNow(); bool shouldSendEnvironments = _myServer->wantSendEnvironments() && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS); - while (packetsSentThisInterval < _myServer->getPacketsPerClientPerInterval() - (shouldSendEnvironments ? 1 : 0)) { + + int clientMaxPacketsPerInterval = nodeData->getMaxVoxelPacketsPerSecond() / INTERVALS_PER_SECOND; + int maxPacketsPerInterval = std::max(clientMaxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval()); + + +printf("deepestLevelVoxelDistributor()... packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n", + 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... uint64_t now = usecTimestampNow(); long elapsedUsec = (now - start); diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index 772bad3f41..ca9eaf8036 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -419,8 +419,8 @@ void VoxelServer::run() { 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 + if (packetData[0] == PACKET_TYPE_VOXEL_QUERY) { + // If we got a PACKET_TYPE_VOXEL_QUERY, then we're talking to an NODE_TYPE_AVATAR, and we // need to make sure we have it in our nodeList. QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*)packetData + numBytesPacketHeader, NUM_BYTES_RFC4122_UUID)); diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 9d992f8b55..e6773ceaa0 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -58,5 +58,6 @@ const float VIEW_FRUSTUM_FOV_OVERSEND = 60.0f; const int UNREASONABLY_DEEP_RECURSION = 20; // use this for something that you want to be shallow, but not spin out const int DANGEROUSLY_DEEP_RECURSION = 200; // use this for something that needs to go deeper +const int DEFAULT_MAX_VOXEL_PPS = 600; // the default maximum PPS we think a voxel server should send to a client #endif \ No newline at end of file From 1c2e5eecd6a231a8369a283d6dbe512a9157b0c6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 28 Oct 2013 12:07:02 -0700 Subject: [PATCH 2/6] send VOXEL_QUERY to out of view voxel servers with PPS of 0 --- interface/src/Application.cpp | 47 +++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 952f6fff8c..f38bb2fc8e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2381,16 +2381,14 @@ void Application::queryVoxels() { } } - // make sure there's at least one voxel server + // assume there's at least one voxel server if (voxelServerCount < 1) { - return; // no voxel servers to talk to, we can bail. + voxelServerCount = 1; } // set our preferred PPS to be exactly evenly divided among all of the voxel servers... int perServerPPS = DEFAULT_MAX_VOXEL_PPS/voxelServerCount; - _voxelQuery.setMaxVoxelPacketsPerSecond(perServerPPS); - UDPSocket* nodeSocket = NodeList::getInstance()->getNodeSocket(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { // only send to the NodeTypes that are NODE_TYPE_VOXEL_SERVER @@ -2412,25 +2410,30 @@ void Application::queryVoxels() { ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds); if (serverFrustumLocation != ViewFrustum::OUTSIDE) { - // set up the packet for sending... - unsigned char* endOfVoxelQueryPacket = voxelQueryPacket; - - // insert packet type/version and node UUID - endOfVoxelQueryPacket += populateTypeAndVersion(endOfVoxelQueryPacket, PACKET_TYPE_VOXEL_QUERY); - QByteArray ownerUUID = nodeList->getOwnerUUID().toRfc4122(); - memcpy(endOfVoxelQueryPacket, ownerUUID.constData(), ownerUUID.size()); - endOfVoxelQueryPacket += ownerUUID.size(); - - // encode the query data... - endOfVoxelQueryPacket += _voxelQuery.getBroadcastData(endOfVoxelQueryPacket); - - int packetLength = endOfVoxelQueryPacket - voxelQueryPacket; - - nodeSocket->send(node->getActiveSocket(), voxelQueryPacket, packetLength); - - // Feed number of bytes to corresponding channel of the bandwidth meter - _bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(packetLength); + //printf("_voxelQuery.setMaxVoxelPacketsPerSecond(perServerPPS=%d)\n",perServerPPS); + _voxelQuery.setMaxVoxelPacketsPerSecond(perServerPPS); + } else { + //printf("_voxelQuery.setMaxVoxelPacketsPerSecond(0)\n"); + _voxelQuery.setMaxVoxelPacketsPerSecond(0); } + // set up the packet for sending... + unsigned char* endOfVoxelQueryPacket = voxelQueryPacket; + + // insert packet type/version and node UUID + endOfVoxelQueryPacket += populateTypeAndVersion(endOfVoxelQueryPacket, PACKET_TYPE_VOXEL_QUERY); + QByteArray ownerUUID = nodeList->getOwnerUUID().toRfc4122(); + memcpy(endOfVoxelQueryPacket, ownerUUID.constData(), ownerUUID.size()); + endOfVoxelQueryPacket += ownerUUID.size(); + + // encode the query data... + endOfVoxelQueryPacket += _voxelQuery.getBroadcastData(endOfVoxelQueryPacket); + + int packetLength = endOfVoxelQueryPacket - voxelQueryPacket; + + nodeSocket->send(node->getActiveSocket(), voxelQueryPacket, packetLength); + + // Feed number of bytes to corresponding channel of the bandwidth meter + _bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(packetLength); } } } From 3ed61db873696d051716c4d823287d0a084f9898 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 28 Oct 2013 12:07:56 -0700 Subject: [PATCH 3/6] add guard around nodeData on delete --- libraries/voxel-server-library/src/NodeWatcher.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/voxel-server-library/src/NodeWatcher.cpp b/libraries/voxel-server-library/src/NodeWatcher.cpp index 894e53b4b5..03384569b8 100644 --- a/libraries/voxel-server-library/src/NodeWatcher.cpp +++ b/libraries/voxel-server-library/src/NodeWatcher.cpp @@ -20,7 +20,9 @@ void NodeWatcher::nodeKilled(Node* node) { // Use this to cleanup our node if (node->getType() == NODE_TYPE_AGENT) { VoxelNodeData* nodeData = (VoxelNodeData*)node->getLinkedData(); - node->setLinkedData(NULL); - delete nodeData; + if (nodeData) { + node->setLinkedData(NULL); + delete nodeData; + } } }; From b10d1118912a54ab8f5a34c0c5800a264ccbd32b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 28 Oct 2013 12:08:52 -0700 Subject: [PATCH 4/6] delete _lastVoxelPacket in ~VoxelNodeData() --- libraries/voxel-server-library/src/VoxelNodeData.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/voxel-server-library/src/VoxelNodeData.cpp b/libraries/voxel-server-library/src/VoxelNodeData.cpp index 741e33e07d..705ea8b2e7 100644 --- a/libraries/voxel-server-library/src/VoxelNodeData.cpp +++ b/libraries/voxel-server-library/src/VoxelNodeData.cpp @@ -108,6 +108,7 @@ void VoxelNodeData::writeToPacket(unsigned char* buffer, int bytes) { VoxelNodeData::~VoxelNodeData() { delete[] _voxelPacket; + delete[] _lastVoxelPacket; if (_voxelSendThread) { _voxelSendThread->terminate(); From ce524714d948f13fdd1009a9357c69974df901b7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 28 Oct 2013 12:09:40 -0700 Subject: [PATCH 5/6] properly call resetVoxelPacket() when suppressing duplicate packets --- libraries/voxel-server-library/src/VoxelSendThread.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/voxel-server-library/src/VoxelSendThread.cpp b/libraries/voxel-server-library/src/VoxelSendThread.cpp index 3ecbd6434e..3a3904e218 100644 --- a/libraries/voxel-server-library/src/VoxelSendThread.cpp +++ b/libraries/voxel-server-library/src/VoxelSendThread.cpp @@ -63,6 +63,7 @@ void VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int& // 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. if (nodeData->shouldSuppressDuplicatePacket()) { + nodeData->resetVoxelPacket(); // we still need to reset it though! return; // without sending... } From e3c64429b961170fb12289d82825f39af707a8e2 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 28 Oct 2013 12:10:30 -0700 Subject: [PATCH 6/6] added SIMPLE_CHILD_ARRAY implementation to temporarily work around memory corruption --- libraries/voxels/src/VoxelNode.cpp | 21 ++++++++++++++++++++- libraries/voxels/src/VoxelNode.h | 5 +++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index e83ffc1c16..456a2d8e58 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -75,7 +75,12 @@ void VoxelNode::init(unsigned char * octalCode) { _childrenArray[i] = NULL; } #endif // def HAS_AUDIT_CHILDREN - + +#ifdef SIMPLE_CHILD_ARRAY + for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { + _simpleChildArray[i] = NULL; + } +#endif _unknownBufferIndex = true; setBufferIndex(GLBUFFER_INDEX_UNKNOWN); @@ -320,6 +325,9 @@ uint64_t VoxelNode::_couldStoreFourChildrenInternally = 0; uint64_t VoxelNode::_couldNotStoreFourChildrenInternally = 0; VoxelNode* VoxelNode::getChildAtIndex(int childIndex) const { +#ifdef SIMPLE_CHILD_ARRAY + return _simpleChildArray[childIndex]; +#else PerformanceWarning warn(false,"getChildAtIndex",false,&_getChildAtIndexTime,&_getChildAtIndexCalls); VoxelNode* result = NULL; int childCount = getChildCount(); @@ -428,6 +436,7 @@ VoxelNode* VoxelNode::getChildAtIndex(int childIndex) const { } #endif // def HAS_AUDIT_CHILDREN return result; +#endif } void VoxelNode::storeTwoChildren(VoxelNode* childOne, VoxelNode* childTwo) { @@ -680,6 +689,14 @@ void VoxelNode::deleteAllChildren() { } void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) { +#ifdef SIMPLE_CHILD_ARRAY + if (child) { + setAtBit(_childBitmask, childIndex); + } else { + clearAtBit(_childBitmask, childIndex); + } + _simpleChildArray[childIndex] = child; +#else PerformanceWarning warn(false,"setChildAtIndex",false,&_setChildAtIndexTime,&_setChildAtIndexCalls); // Here's how we store things... @@ -1020,6 +1037,8 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) { _childrenArray[childIndex] = child; auditChildren("setChildAtIndex()"); #endif // def HAS_AUDIT_CHILDREN + +#endif } diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index f76be6227f..c9e892ebb9 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -10,6 +10,7 @@ #define __hifi__VoxelNode__ //#define HAS_AUDIT_CHILDREN +#define SIMPLE_CHILD_ARRAY #include #include "AABox.h" @@ -172,6 +173,10 @@ private: uint64_t _lastChanged; /// Client and server, timestamp this node was last changed, 8 bytes /// Client and server, pointers to child nodes, various encodings +#ifdef SIMPLE_CHILD_ARRAY + VoxelNode* _simpleChildArray[8]; /// Only used when HAS_AUDIT_CHILDREN is enabled to help debug children encoding +#endif + union children_t { VoxelNode* single; int32_t offsetsTwoChildren[2];