From 015adeedcb95f5e1c3a4fca23d2a4dee49572f89 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 24 Oct 2013 13:21:09 -0700 Subject: [PATCH] first cut at splitting out PACKET_TYPE_VOXEL_QUERY from PACKET_TYPE_HEAD_DATA --- 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 + libraries/voxels/src/VoxelQuery.cpp | 131 ++++++++++++ libraries/voxels/src/VoxelQuery.h | 105 ++++++++++ 18 files changed, 510 insertions(+), 314 deletions(-) create mode 100644 libraries/voxels/src/VoxelQuery.cpp create mode 100644 libraries/voxels/src/VoxelQuery.h 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 diff --git a/libraries/voxels/src/VoxelQuery.cpp b/libraries/voxels/src/VoxelQuery.cpp new file mode 100644 index 0000000000..507c086619 --- /dev/null +++ b/libraries/voxels/src/VoxelQuery.cpp @@ -0,0 +1,131 @@ +// +// VoxelQuery.cpp +// hifi +// +// Created by Brad Hefta-Gaub on 10/24/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#include +#include +#include + +#include +#include +#include +#include +#include "VoxelConstants.h" + +#include "VoxelQuery.h" + +using namespace std; + +static const float fingerVectorRadix = 4; // bits of precision when converting from float<->fixed + +VoxelQuery::VoxelQuery(Node* owningNode) : + NodeData(owningNode), + _uuid(), + _cameraPosition(0,0,0), + _cameraOrientation(), + _cameraFov(0.0f), + _cameraAspectRatio(0.0f), + _cameraNearClip(0.0f), + _cameraFarClip(0.0f), + _wantColor(true), + _wantDelta(true), + _wantLowResMoving(true), + _wantOcclusionCulling(true), + _maxVoxelPPS(DEFAULT_MAX_VOXEL_PPS) +{ + +} + +VoxelQuery::~VoxelQuery() { +} + +int VoxelQuery::getBroadcastData(unsigned char* destinationBuffer) { + unsigned char* bufferStart = destinationBuffer; + + // TODO: DRY this up to a shared method + // that can pack any type given the number of bytes + // and return the number of bytes to push the pointer + + // UUID + QByteArray uuidByteArray = _uuid.toRfc4122(); + memcpy(destinationBuffer, uuidByteArray.constData(), uuidByteArray.size()); + destinationBuffer += uuidByteArray.size(); + + // 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); + + // 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); } + + *destinationBuffer++ = bitItems; + + // desired Max Voxel PPS + memcpy(destinationBuffer, &_maxVoxelPPS, sizeof(_maxVoxelPPS)); + destinationBuffer += sizeof(_maxVoxelPPS); + + return destinationBuffer - bufferStart; +} + +// called on the other nodes - assigns it to my views of the others +int VoxelQuery::parseData(unsigned char* sourceBuffer, int numBytes) { + + // increment to push past the packet header + int numBytesPacketHeader = numBytesForPacketHeader(sourceBuffer); + sourceBuffer += numBytesPacketHeader; + + unsigned char* startPosition = sourceBuffer; + + // push past the node session UUID + sourceBuffer += NUM_BYTES_RFC4122_UUID; + + // user UUID + _uuid = QUuid::fromRfc4122(QByteArray((char*) sourceBuffer, NUM_BYTES_RFC4122_UUID)); + sourceBuffer += NUM_BYTES_RFC4122_UUID; + + // 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); + + // 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); + + // desired Max Voxel PPS + memcpy(&_maxVoxelPPS, sourceBuffer, sizeof(_maxVoxelPPS)); + sourceBuffer += sizeof(_maxVoxelPPS); + + return sourceBuffer - startPosition; +} + +glm::vec3 VoxelQuery::calculateCameraDirection() const { + glm::vec3 direction = glm::vec3(_cameraOrientation * glm::vec4(IDENTITY_FRONT, 0.0f)); + return direction; +} + diff --git a/libraries/voxels/src/VoxelQuery.h b/libraries/voxels/src/VoxelQuery.h new file mode 100644 index 0000000000..ec65859c70 --- /dev/null +++ b/libraries/voxels/src/VoxelQuery.h @@ -0,0 +1,105 @@ +// +// VoxelQuery.h +// hifi +// +// Created by Stephen Birarda on 4/9/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __hifi__VoxelQuery__ +#define __hifi__VoxelQuery__ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include + +// 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 WANT_OCCLUSION_CULLING_BIT = 7; // 8th bit + +class VoxelQuery : public NodeData { + Q_OBJECT + +public: + VoxelQuery(Node* owningNode = NULL); + ~VoxelQuery(); + + int getBroadcastData(unsigned char* destinationBuffer); + int parseData(unsigned char* sourceBuffer, int numBytes); + + QUuid& getUUID() { return _uuid; } + void setUUID(const QUuid& uuid) { _uuid = uuid; } + + // 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; } + + // 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; } + int getMaxVoxelPacketsPerSecond() const { return _maxVoxelPPS; } + +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; } + void setMaxVoxelPacketsPerSecond(int maxVoxelPPS) { _maxVoxelPPS = maxVoxelPPS; } + +protected: + QUuid _uuid; + + // camera details for the avatar + glm::vec3 _cameraPosition; + glm::quat _cameraOrientation; + float _cameraFov; + float _cameraAspectRatio; + float _cameraNearClip; + float _cameraFarClip; + glm::vec3 _cameraEyeOffsetPosition; + + // voxel server sending items + bool _wantColor; + bool _wantDelta; + bool _wantLowResMoving; + bool _wantOcclusionCulling; + int _maxVoxelPPS; + +private: + // privatize the copy constructor and assignment operator so they cannot be called + VoxelQuery(const VoxelQuery&); + VoxelQuery& operator= (const VoxelQuery&); +}; + +#endif /* defined(__hifi__VoxelQuery__) */