Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jeffrey Ventrella 2013-05-13 16:54:41 -07:00
commit 6e3ab12411
12 changed files with 360 additions and 83 deletions

View file

@ -104,6 +104,13 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
_tree->readBitstreamToTree(voxelData, numBytes - 1);
}
break;
case PACKET_HEADER_VOXEL_DATA_MONOCHROME:
{
PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()");
// ask the VoxelTree to read the MONOCHROME bitstream into the tree
_tree->readBitstreamToTree(voxelData, numBytes - 1, false);
}
break;
case PACKET_HEADER_ERASE_VOXEL:
// ask the tree to read the "remove" bitstream
_tree->processRemoveVoxelBitstream(sourceBuffer, numBytes);

View file

@ -160,6 +160,8 @@ bool paintOn = false; // Whether to paint voxels as you fly aroun
VoxelDetail paintingVoxel; // The voxel we're painting if we're painting
unsigned char dominantColor = 0; // The dominant color of the voxel we're painting
bool perfStatsOn = false; // Do we want to display perfStats?
bool wantMonochrome = false; // ask server to send us in monochrome
bool wantResIn = false; // ask server to res in
bool logOn = true; // Whether to show on-screen log
@ -1281,6 +1283,22 @@ int setRenderWarnings(int state) {
return value;
}
int setWantResIn(int state) {
int value = setValue(state, &::wantResIn);
if (state == MENU_ROW_PICKED) {
::myAvatar.setWantResIn(::wantResIn);
}
return value;
}
int setWantMonochrome(int state) {
int value = setValue(state, &::wantMonochrome);
if (state == MENU_ROW_PICKED) {
::myAvatar.setWantColor(!::wantMonochrome);
}
return value;
}
int setDisplayFrustum(int state) {
return setValue(state, &::frustumOn);
}
@ -1373,6 +1391,8 @@ int doFalseColorizeInView(int state) {
return state;
}
const char* modeAll = " - All ";
const char* modeVectors = " - Vectors ";
const char* modePlanes = " - Planes ";
@ -1444,6 +1464,8 @@ void initMenu() {
menuColumnDebug->addRow("FALSE Color Voxel Out of View", doFalseColorizeInView);
menuColumnDebug->addRow("Show TRUE Colors", doTrueVoxelColors);
menuColumnDebug->addRow("Calculate Tree Stats", doTreeStats);
menuColumnDebug->addRow("Wants Res-In", setWantResIn);
menuColumnDebug->addRow("Wants Monochrome", setWantMonochrome);
}
void testPointToVoxel() {
@ -1741,6 +1763,7 @@ void* networkReceive(void* args) {
myAvatar.processTransmitterData(incomingPacket, bytesReceived);
break;
case PACKET_HEADER_VOXEL_DATA:
case PACKET_HEADER_VOXEL_DATA_MONOCHROME:
case PACKET_HEADER_Z_COMMAND:
case PACKET_HEADER_ERASE_VOXEL:
voxels.parseData(incomingPacket, bytesReceived);

View file

@ -34,29 +34,6 @@ int unpackFloatAngleFromTwoByte(uint16_t* byteAnglePointer, float* destinationPo
return sizeof(uint16_t);
}
AvatarData::AvatarData() :
_handPosition(0,0,0),
_bodyYaw(-90.0),
_bodyPitch(0.0),
_bodyRoll(0.0),
_headYaw(0),
_headPitch(0),
_headRoll(0),
_headLeanSideways(0),
_headLeanForward(0),
_handState(0),
_cameraPosition(0,0,0),
_cameraDirection(0,0,0),
_cameraUp(0,0,0),
_cameraRight(0,0,0),
_cameraFov(0.0f),
_cameraAspectRatio(0.0f),
_cameraNearClip(0.0f),
_cameraFarClip(0.0f),
_keyState(NO_KEY_DOWN) {
}
AvatarData::~AvatarData() {
}
@ -130,6 +107,10 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
memcpy(destinationBuffer, _chatMessage.data(), _chatMessage.size() * sizeof(char));
destinationBuffer += _chatMessage.size() * sizeof(char);
// voxel sending features...
*destinationBuffer++ = _wantResIn;
*destinationBuffer++ = _wantColor;
return destinationBuffer - bufferStart;
}
@ -201,6 +182,10 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
int chatMessageSize = *sourceBuffer++;
_chatMessage = string((char*)sourceBuffer, chatMessageSize);
sourceBuffer += chatMessageSize * sizeof(char);
// voxel sending features...
_wantResIn = (bool)*sourceBuffer++;
_wantColor = (bool)*sourceBuffer++;
return sourceBuffer - startPosition;
}

View file

@ -24,7 +24,30 @@ enum KeyState
class AvatarData : public AgentData {
public:
AvatarData();
AvatarData() :
_handPosition(0,0,0),
_bodyYaw(-90.0),
_bodyPitch(0.0),
_bodyRoll(0.0),
_headYaw(0),
_headPitch(0),
_headRoll(0),
_headLeanSideways(0),
_headLeanForward(0),
_handState(0),
_cameraPosition(0,0,0),
_cameraDirection(0,0,0),
_cameraUp(0,0,0),
_cameraRight(0,0,0),
_cameraFov(0.0f),
_cameraAspectRatio(0.0f),
_cameraNearClip(0.0f),
_cameraFarClip(0.0f),
_keyState(NO_KEY_DOWN),
_wantResIn(false),
_wantColor(true) { };
~AvatarData();
AvatarData* clone() const;
@ -96,6 +119,12 @@ public:
// chat message
void setChatMessage(const std::string& msg) { _chatMessage = msg; }
const std::string& chatMessage () const { return _chatMessage; }
// related to Voxel Sending strategies
bool getWantResIn() const { return _wantResIn; }
bool getWantColor() const { return _wantColor; }
void setWantResIn(bool wantResIn) { _wantResIn = wantResIn; }
void setWantColor(bool wantColor) { _wantColor = wantColor; }
protected:
glm::vec3 _position;
@ -137,6 +166,9 @@ protected:
// chat message
std::string _chatMessage;
bool _wantResIn;
bool _wantColor;
};
#endif /* defined(__hifi__AvatarData__) */

View file

@ -23,6 +23,7 @@ const PACKET_HEADER PACKET_HEADER_INJECT_AUDIO = 'I';
const PACKET_HEADER PACKET_HEADER_SET_VOXEL = 'S';
const PACKET_HEADER PACKET_HEADER_ERASE_VOXEL = 'E';
const PACKET_HEADER PACKET_HEADER_VOXEL_DATA = 'V';
const PACKET_HEADER PACKET_HEADER_VOXEL_DATA_MONOCHROME = 'v';
const PACKET_HEADER PACKET_HEADER_BULK_AVATAR_DATA = 'X';
const PACKET_HEADER PACKET_HEADER_TRANSMITTER_DATA = 't';
const PACKET_HEADER PACKET_HEADER_ENVIRONMENT_DATA = 'e';

View file

@ -0,0 +1,42 @@
//
// PointerStack.cpp
// hifi
//
// Created by Brad Hefta-Gaub on 5/11/2013
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#include "PointerStack.h"
#include <stdio.h>
PointerStack::~PointerStack() {
deleteAll();
}
void PointerStack::deleteAll() {
if (_elements) {
delete[] _elements;
}
_elements = NULL;
_elementsInUse = 0;
_sizeOfElementsArray = 0;
}
const int GROW_BY = 100;
void PointerStack::growAndPush(void* element) {
//printf("PointerStack::growAndPush() _sizeOfElementsArray=%d",_sizeOfElementsArray);
void** oldElements = _elements;
_elements = new void* [_sizeOfElementsArray + GROW_BY];
_sizeOfElementsArray += GROW_BY;
// If we had an old stack...
if (oldElements) {
// copy old elements into the new stack
memcpy(_elements, oldElements, _elementsInUse * sizeof(void*));
delete[] oldElements;
}
_elements[_elementsInUse] = element;
_elementsInUse++;
}

View file

@ -0,0 +1,59 @@
//
// PointerStack.h
// hifi
//
// Created by Brad Hefta-Gaub on 4/25/2013
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
//
#ifndef __hifi__PointerStack__
#define __hifi__PointerStack__
#include <cstring> // for NULL
class PointerStack {
public:
PointerStack() :
_elements(NULL),
_elementsInUse(0),
_sizeOfElementsArray(0) {};
~PointerStack();
void push(void* element) {
if (_sizeOfElementsArray < _elementsInUse + 1) {
return growAndPush(element);
}
_elements[_elementsInUse] = element;
_elementsInUse++;
};
void* pop() {
if (_elementsInUse) {
// get the last element
void* element = _elements[_elementsInUse - 1];
// reduce the count
_elementsInUse--;
return element;
}
return NULL;
};
void* top() const { return (_elementsInUse) ? _elements[_elementsInUse - 1] : NULL; }
bool isEmpty() const { return (_elementsInUse == 0); };
bool empty() const { return (_elementsInUse == 0); };
int count() const { return _elementsInUse; };
int size() const { return _elementsInUse; };
private:
void growAndPush(void* element);
void deleteAll();
void** _elements;
int _elementsInUse;
int _sizeOfElementsArray;
};
#endif /* defined(__hifi__PointerStack__) */

View file

@ -115,7 +115,7 @@ VoxelNode* VoxelTree::createMissingNode(VoxelNode* lastParentNode, unsigned char
}
}
int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, int bytesLeftToRead) {
int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData, int bytesLeftToRead, bool includeColor) {
// instantiate variable for bytes already read
int bytesRead = 1;
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
@ -133,9 +133,11 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData,
}
// pull the color for this child
nodeColor newColor;
memcpy(newColor, nodeData + bytesRead, 3);
newColor[3] = 1;
nodeColor newColor = { 128, 128, 128, 1};
if (includeColor) {
memcpy(newColor, nodeData + bytesRead, 3);
bytesRead += 3;
}
bool nodeWasDirty = destinationNode->getChildAtIndex(i)->isDirty();
destinationNode->getChildAtIndex(i)->setColor(newColor);
bool nodeIsDirty = destinationNode->getChildAtIndex(i)->isDirty();
@ -147,8 +149,6 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData,
}
this->voxelsColored++;
this->voxelsColoredStats.updateAverage(1);
bytesRead += 3;
}
}
@ -180,7 +180,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData,
// tell the child to read the subsequent data
bytesRead += readNodeData(destinationNode->getChildAtIndex(childIndex),
nodeData + bytesRead,
bytesLeftToRead - bytesRead);
bytesLeftToRead - bytesRead, includeColor);
}
childIndex++;
@ -189,7 +189,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData,
return bytesRead;
}
void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes) {
void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes, bool includeColor) {
int bytesRead = 0;
unsigned char* bitstreamAt = bitstream;
@ -218,7 +218,7 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int
int theseBytesRead = 0;
theseBytesRead += octalCodeBytes;
theseBytesRead += readNodeData(bitstreamRootNode, bitstreamAt + octalCodeBytes,
bufferSizeBytes - (bytesRead + octalCodeBytes));
bufferSizeBytes - (bytesRead + octalCodeBytes), includeColor);
// skip bitstream to new startPoint
bitstreamAt += theseBytesRead;
@ -747,7 +747,7 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe
}
int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
VoxelNodeBag& bag, const ViewFrustum* viewFrustum) const {
VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor) const {
// How many bytes have we written so far at this level;
int bytesWritten = 0;
@ -767,14 +767,14 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned
int currentEncodeLevel = 0;
int childBytesWritten = encodeTreeBitstreamRecursion(maxEncodeLevel, currentEncodeLevel,
node, outputBuffer, availableBytes, bag, viewFrustum);
node, outputBuffer, availableBytes, bag, viewFrustum, includeColor);
// if childBytesWritten == 1 then something went wrong... that's not possible
assert(childBytesWritten != 1);
// if childBytesWritten == 2, then it can only mean that the lower level trees don't exist or for some reason
// couldn't be written... so reset them here...
if (childBytesWritten == 2) {
// if includeColor and childBytesWritten == 2, then it can only mean that the lower level trees don't exist or for some reason
// couldn't be written... so reset them here... This isn't true for the non-color included case
if (includeColor && childBytesWritten == 2) {
childBytesWritten = 0;
}
@ -790,7 +790,7 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned
int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
VoxelNodeBag& bag, const ViewFrustum* viewFrustum) const {
VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor) const {
// How many bytes have we written so far at this level;
int bytesAtThisLevel = 0;
@ -875,11 +875,13 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
bytesAtThisLevel += sizeof(childrenColoredBits); // keep track of byte count
// write the color data...
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
if (oneAtBit(childrenColoredBits, i)) {
memcpy(writeToThisLevelBuffer, &node->getChildAtIndex(i)->getColor(), BYTES_PER_COLOR);
writeToThisLevelBuffer += BYTES_PER_COLOR; // move the pointer for color
bytesAtThisLevel += BYTES_PER_COLOR; // keep track of byte count for color
if (includeColor) {
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
if (oneAtBit(childrenColoredBits, i)) {
memcpy(writeToThisLevelBuffer, &node->getChildAtIndex(i)->getColor(), BYTES_PER_COLOR);
writeToThisLevelBuffer += BYTES_PER_COLOR; // move the pointer for color
bytesAtThisLevel += BYTES_PER_COLOR; // keep track of byte count for color
}
}
}
// write the child exist bits
@ -922,7 +924,8 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
int thisLevel = currentEncodeLevel;
int childTreeBytesOut = encodeTreeBitstreamRecursion(maxEncodeLevel, thisLevel, childNode,
outputBuffer, availableBytes, bag, viewFrustum);
outputBuffer, availableBytes, bag,
viewFrustum, includeColor);
// if the child wrote 0 bytes, it means that nothing below exists or was in view, or we ran out of space,
// basically, the children below don't contain any info.
@ -940,7 +943,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
// so, if the child returns 2 bytes out, we can actually consider that an empty tree also!!
//
// we can make this act like no bytes out, by just resetting the bytes out in this case
if (childTreeBytesOut == 2) {
if (includeColor && childTreeBytesOut == 2) {
childTreeBytesOut = 0; // this is the degenerate case of a tree with no colors and no child trees
}
@ -975,7 +978,7 @@ bool VoxelTree::readFromFileV2(const char* fileName) {
// read the entire file into a buffer, WHAT!? Why not.
unsigned char* entireFile = new unsigned char[fileLength];
file.read((char*)entireFile, fileLength);
readBitstreamToTree(entireFile, fileLength);
readBitstreamToTree(entireFile, fileLength, true);
delete[] entireFile;
file.close();
@ -999,7 +1002,8 @@ void VoxelTree::writeToFileV2(const char* fileName) const {
while (!nodeBag.isEmpty()) {
VoxelNode* subTree = nodeBag.extract();
bytesWritten = encodeTreeBitstream(INT_MAX, subTree, &outputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, nodeBag, NULL);
bytesWritten = encodeTreeBitstream(INT_MAX, subTree, &outputBuffer[0],
MAX_VOXEL_PACKET_SIZE - 1, nodeBag, NULL, true);
file.write((const char*)&outputBuffer[0], bytesWritten);
}

View file

@ -40,7 +40,7 @@ public:
void eraseAllVoxels();
void processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes);
void readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes);
void readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes, bool includeColor = true);
void readCodeColorBufferToTree(unsigned char *codeColorBuffer);
void deleteVoxelCodeFromTree(unsigned char *codeBuffer, bool stage = false);
void printTreeForDebugging(VoxelNode *startNode);
@ -55,7 +55,7 @@ public:
void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL);
int encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
VoxelNodeBag& bag, const ViewFrustum* viewFrustum) const;
VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor = true) const;
int searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag);
@ -79,7 +79,7 @@ public:
private:
int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
VoxelNodeBag& bag, const ViewFrustum* viewFrustum) const;
VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor) const;
int searchForColoredNodesRecursion(int maxSearchLevel, int& currentSearchLevel,
VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag);
@ -89,7 +89,7 @@ private:
void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData);
VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const;
VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate);
int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes);
int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes, bool includeColor = true);
bool _isDirty;
unsigned long int _nodesChangedFromBitstream;

View file

@ -24,6 +24,15 @@ struct PairableDevice {
sockaddr_in localSocket;
};
struct RequestingClient {
char address[INET_ADDRSTRLEN];
int port;
};
UDPSocket serverSocket(PAIRING_SERVER_LISTEN_PORT);
PairableDevice* lastDevice = NULL;
RequestingClient* lastClient = NULL;
int indexOfFirstOccurenceOfCharacter(char* haystack, char needle) {
int currentIndex = 0;
@ -34,70 +43,81 @@ int indexOfFirstOccurenceOfCharacter(char* haystack, char needle) {
return currentIndex;
}
void sendLastClientToLastDevice() {
char pairData[INET_ADDRSTRLEN + 6] = {};
int bytesWritten = sprintf(pairData, "%s:%d", ::lastClient->address, ::lastClient->port);
::serverSocket.send((sockaddr*) &::lastDevice->sendingSocket, pairData, bytesWritten);
}
int main(int argc, const char* argv[]) {
UDPSocket serverSocket(PAIRING_SERVER_LISTEN_PORT);
sockaddr_in senderSocket;
char senderData[MAX_PACKET_SIZE_BYTES] = {};
ssize_t receivedBytes = 0;
std::vector<PairableDevice> devices;
while (true) {
if (serverSocket.receive((sockaddr *)&senderSocket, &senderData, &receivedBytes)) {
if (::serverSocket.receive((sockaddr*) &senderSocket, &senderData, &receivedBytes)) {
if (senderData[0] == 'A') {
// this is a device reporting itself as available
// create a new PairableDevice
PairableDevice newDevice = {};
PairableDevice tempDevice = {};
char deviceAddress[INET_ADDRSTRLEN] = {};
int socketPort = 0;
int numMatches = sscanf(senderData, "Available %s%[^:]:%d %s",
newDevice.identifier,
int numMatches = sscanf(senderData, "Available %s %[^:]:%d %s",
tempDevice.identifier,
deviceAddress,
&socketPort,
newDevice.name);
tempDevice.name);
if (numMatches >= 3) {
// if we have fewer than 6 matches the packet wasn't properly formatted
// if we have fewer than 3 matches the packet wasn't properly formatted
// setup the localSocket for the pairing device
newDevice.localSocket.sin_family = AF_INET;
inet_pton(AF_INET, deviceAddress, &newDevice);
newDevice.localSocket.sin_port = socketPort;
tempDevice.localSocket.sin_family = AF_INET;
inet_pton(AF_INET, deviceAddress, &::lastDevice);
tempDevice.localSocket.sin_port = socketPort;
// store this device's sending socket so we can talk back to it
newDevice.sendingSocket = senderSocket;
tempDevice.sendingSocket = senderSocket;
// push this new device into the vector
printf("Adding device %s (%s) - %s:%d to list\n",
newDevice.identifier,
newDevice.name,
printf("New last device is %s (%s) at %s:%d\n",
tempDevice.identifier,
tempDevice.name,
deviceAddress,
socketPort);
// copy the tempDevice to the persisting lastDevice
::lastDevice = new PairableDevice(tempDevice);
devices.push_back(newDevice);
if (::lastClient) {
sendLastClientToLastDevice();
}
}
} else if (senderData[0] == 'F') {
// this is a client looking to pair with a device
// send the most recent device this address so it can attempt to pair
char requestorAddress[INET_ADDRSTRLEN] = {};
int requestorPort = 0;
RequestingClient tempClient = {};
int requestorMatches = sscanf(senderData, "Find %[^:]:%d", requestorAddress, &requestorPort);
printf("Find request from interface client at %s:%d\n", requestorAddress, requestorPort);
int requestorMatches = sscanf(senderData, "Find %[^:]:%d",
tempClient.address,
&tempClient.port);
if (requestorMatches == 2) {
PairableDevice lastDevice = devices[devices.size() - 1];
// good data, copy the tempClient to the persisting lastInterfaceClient
::lastClient = new RequestingClient(tempClient);
char pairData[INET_ADDRSTRLEN + 6] = {};
sprintf(pairData, "%s:%d", requestorAddress, requestorPort);
printf("New last client is at %s:%d\n",
::lastClient->address,
::lastClient->port);
serverSocket.send((sockaddr*) &lastDevice.sendingSocket, pairData, strlen(pairData));
if (::lastDevice) {
sendLastClientToLastDevice();
}
}
}
}

View file

@ -25,7 +25,7 @@ void VoxelAgentData::init() {
}
void VoxelAgentData::resetVoxelPacket() {
_voxelPacket[0] = PACKET_HEADER_VOXEL_DATA;
_voxelPacket[0] = getWantColor() ? PACKET_HEADER_VOXEL_DATA : PACKET_HEADER_VOXEL_DATA_MONOCHROME;
_voxelPacketAt = &_voxelPacket[1];
_voxelPacketAvailableBytes = MAX_VOXEL_PACKET_SIZE - 1;
_voxelPacketWaiting = false;

View file

@ -104,7 +104,13 @@ void eraseVoxelTreeAndCleanupAgentVisitData() {
}
void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAgentData* agentData, ViewFrustum& viewFrustum) {
// Version of voxel distributor that sends each LOD level at a time
void resInVoxelDistributor(AgentList* agentList,
AgentList::iterator& agent,
VoxelAgentData* agentData,
ViewFrustum& viewFrustum) {
printf("resInVoxelDistributor()\n");
bool searchReset = false;
int searchLoops = 0;
int searchLevelWas = agentData->getMaxSearchLevel();
@ -158,7 +164,8 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
VoxelNode* subTree = agentData->nodeBag.extract();
bytesWritten = randomTree.encodeTreeBitstream(agentData->getMaxSearchLevel(), subTree,
&tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
agentData->nodeBag, &viewFrustum);
agentData->nodeBag, &viewFrustum,
agentData->getWantColor());
if (agentData->getAvailable() >= bytesWritten) {
agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
@ -216,6 +223,99 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
}
}
// Version of voxel distributor that sends the deepest LOD level at once
void deepestLevelVoxelDistributor(AgentList* agentList,
AgentList::iterator& agent,
VoxelAgentData* agentData,
ViewFrustum& viewFrustum) {
printf("deepestLevelVoxelDistributor()\n");
int maxLevelReached = 0;
double start = usecTimestampNow();
if (agentData->nodeBag.isEmpty()) {
maxLevelReached = randomTree.searchForColoredNodes(INT_MAX, randomTree.rootNode, viewFrustum, agentData->nodeBag);
}
double end = usecTimestampNow();
double elapsedmsec = (end - start)/1000.0;
if (elapsedmsec > 100) {
if (elapsedmsec > 1000) {
double elapsedsec = (end - start)/1000000.0;
printf("WARNING! searchForColoredNodes() took %lf seconds to identify %d nodes at level %d\n",
elapsedsec, agentData->nodeBag.count(), maxLevelReached);
} else {
printf("WARNING! searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d\n",
elapsedmsec, agentData->nodeBag.count(), maxLevelReached);
}
} else if (::debugVoxelSending) {
printf("searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d\n",
elapsedmsec, agentData->nodeBag.count(), maxLevelReached);
}
// If we have something in our nodeBag, then turn them into packets and send them out...
if (!agentData->nodeBag.isEmpty()) {
static unsigned char tempOutputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static
int bytesWritten = 0;
int packetsSentThisInterval = 0;
int truePacketsSent = 0;
int trueBytesSent = 0;
double start = usecTimestampNow();
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - 1) {
if (!agentData->nodeBag.isEmpty()) {
VoxelNode* subTree = agentData->nodeBag.extract();
bytesWritten = randomTree.encodeTreeBitstream(INT_MAX, subTree,
&tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
agentData->nodeBag, &viewFrustum,
agentData->getWantColor());
if (agentData->getAvailable() >= bytesWritten) {
agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
} else {
agentList->getAgentSocket().send(agent->getActiveSocket(),
agentData->getPacket(), agentData->getPacketLength());
trueBytesSent += agentData->getPacketLength();
truePacketsSent++;
packetsSentThisInterval++;
agentData->resetVoxelPacket();
agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
}
} else {
if (agentData->isPacketWaiting()) {
agentList->getAgentSocket().send(agent->getActiveSocket(),
agentData->getPacket(), agentData->getPacketLength());
trueBytesSent += agentData->getPacketLength();
truePacketsSent++;
agentData->resetVoxelPacket();
}
packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left
}
}
// send the environment packet
int envPacketLength = environmentData.getBroadcastData(tempOutputBuffer);
agentList->getAgentSocket().send(agent->getActiveSocket(), tempOutputBuffer, envPacketLength);
trueBytesSent += envPacketLength;
truePacketsSent++;
double end = usecTimestampNow();
double elapsedmsec = (end - start)/1000.0;
if (elapsedmsec > 100) {
if (elapsedmsec > 1000) {
double elapsedsec = (end - start)/1000000.0;
printf("WARNING! packetLoop() took %lf seconds to generate %d bytes in %d packets %d nodes still to send\n",
elapsedsec, trueBytesSent, truePacketsSent, agentData->nodeBag.count());
} else {
printf("WARNING! packetLoop() took %lf milliseconds to generate %d bytes in %d packets, %d nodes still to send\n",
elapsedmsec, trueBytesSent, truePacketsSent, agentData->nodeBag.count());
}
} else if (::debugVoxelSending) {
printf("packetLoop() took %lf milliseconds to generate %d bytes in %d packets, %d nodes still to send\n",
elapsedmsec, trueBytesSent, truePacketsSent, agentData->nodeBag.count());
}
}
}
void persistVoxelsWhenDirty() {
// check the dirty bit and persist here...
if (::wantVoxelPersist && ::randomTree.isDirty()) {
@ -253,7 +353,11 @@ void *distributeVoxelsToListeners(void *args) {
viewFrustum.calculate();
voxelDistributor(agentList, agent, agentData, viewFrustum);
if (agentData->getWantResIn()) {
resInVoxelDistributor(agentList, agent, agentData, viewFrustum);
} else {
deepestLevelVoxelDistributor(agentList, agent, agentData, viewFrustum);
}
}
}