first cut at splitting out PACKET_TYPE_VOXEL_QUERY from PACKET_TYPE_HEAD_DATA

This commit is contained in:
ZappoMan 2013-10-24 13:21:09 -07:00
parent ba5db325aa
commit 015adeedcb
18 changed files with 510 additions and 314 deletions

View file

@ -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)

View file

@ -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));
}
/////////////////////////////////////////////////////////////////////////////////////

View file

@ -22,6 +22,7 @@
#include <NetworkPacket.h>
#include <NodeList.h>
#include <PacketHeaders.h>
#include <VoxelQuery.h>
#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

View file

@ -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<uint16_t>::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<uint16_t>::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<uint16_t>::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<uint16_t>::max()) * 2.0) - 1.0;
quatOutput.y = ((quatParts[1] / (float) std::numeric_limits<uint16_t>::max()) * 2.0) - 1.0;
quatOutput.z = ((quatParts[2] / (float) std::numeric_limits<uint16_t>::max()) * 2.0) - 1.0;
quatOutput.w = ((quatParts[3] / (float) std::numeric_limits<uint16_t>::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<int16_t>::max() / SMALL_LIMIT);
ratioHolder = floorf(ratio * SMALL_RATIO_CONVERSION_RATIO);
} else {
const float LARGE_RATIO_CONVERSION_RATIO = std::numeric_limits<int16_t>::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<int16_t>::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<int16_t>::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<int16_t>::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<int16_t>::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<int16_t>::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);
}

View file

@ -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<JointData> _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__) */

View file

@ -8,6 +8,7 @@
#include "HandData.h"
#include "AvatarData.h"
#include <SharedUtil.h>
// Glove flags
#define GLOVE_FLAG_RAVE 0x01

View file

@ -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})

View file

@ -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;

View file

@ -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;

View file

@ -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<uint16_t>::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<uint16_t>::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<uint16_t>::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<uint16_t>::max()) * 2.0) - 1.0;
quatOutput.y = ((quatParts[1] / (float) std::numeric_limits<uint16_t>::max()) * 2.0) - 1.0;
quatOutput.z = ((quatParts[2] / (float) std::numeric_limits<uint16_t>::max()) * 2.0) - 1.0;
quatOutput.w = ((quatParts[3] / (float) std::numeric_limits<uint16_t>::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<int16_t>::max() / SMALL_LIMIT);
ratioHolder = floorf(ratio * SMALL_RATIO_CONVERSION_RATIO);
} else {
const float LARGE_RATIO_CONVERSION_RATIO = std::numeric_limits<int16_t>::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<int16_t>::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<int16_t>::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<int16_t>::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<int16_t>::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<int16_t>::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);
}

View file

@ -13,6 +13,9 @@
#include <stdint.h>
#include <unistd.h>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <QtCore/QDebug>
#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__) */

View file

@ -14,7 +14,7 @@
#include "VoxelSendThread.h"
VoxelNodeData::VoxelNodeData(Node* owningNode) :
AvatarData(owningNode),
VoxelQuery(owningNode),
_viewSent(false),
_voxelPacketAvailableBytes(MAX_VOXEL_PACKET_SIZE),
_maxSearchLevel(1),

View file

@ -11,7 +11,7 @@
#include <iostream>
#include <NodeData.h>
#include <AvatarData.h>
#include <VoxelQuery.h>
#include <CoverageMap.h>
#include <VoxelConstants.h>
@ -21,7 +21,7 @@
class VoxelSendThread;
class VoxelServer;
class VoxelNodeData : public AvatarData {
class VoxelNodeData : public VoxelQuery {
public:
VoxelNodeData(Node* owningNode);
~VoxelNodeData();

View file

@ -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);

View file

@ -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));

View file

@ -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

View file

@ -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 <cstdio>
#include <cstring>
#include <stdint.h>
#include <NodeList.h>
#include <PacketHeaders.h>
#include <SharedUtil.h>
#include <UUID.h>
#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;
}

View file

@ -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 <string>
#include <inttypes.h>
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <QtCore/QObject>
#include <QtCore/QUuid>
#include <QtCore/QVariantMap>
#include <RegisteredMetaTypes.h>
#include <NodeData.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 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__) */