mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 09:33:36 +02:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
6e3ab12411
12 changed files with 360 additions and 83 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -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';
|
||||
|
|
42
libraries/shared/src/PointerStack.cpp
Normal file
42
libraries/shared/src/PointerStack.cpp
Normal 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++;
|
||||
}
|
||||
|
59
libraries/shared/src/PointerStack.h
Normal file
59
libraries/shared/src/PointerStack.h
Normal 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__) */
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue