From 482e65c296e1390fd9129137263c830f4a39c781 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 19 Mar 2013 15:49:12 -0700 Subject: [PATCH 01/21] move randomBoolean and randomColorValue methods to SharedUtil --- shared/src/SharedUtil.cpp | 28 ++++++++++++++++++++++++++-- shared/src/SharedUtil.h | 8 +++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/shared/src/SharedUtil.cpp b/shared/src/SharedUtil.cpp index 85a7187c0c..404ac9d5cb 100644 --- a/shared/src/SharedUtil.cpp +++ b/shared/src/SharedUtil.cpp @@ -24,7 +24,16 @@ float randFloat () { return (rand() % 10000)/10000.f; } -void outputBits(char byte) { + +unsigned char randomColorValue(uint8_t miniumum) { + return miniumum + (rand() % (255 - miniumum)); +} + +bool randomBoolean() { + return rand() % 2; +} + +void outputBits(unsigned char byte) { printf("%d: ", byte); for (int i = 0; i < 8; i++) { @@ -32,4 +41,19 @@ void outputBits(char byte) { } printf("\n"); -} \ No newline at end of file +} + +int8_t numberOfOnes(unsigned char byte) { + return (byte >> 7) + + ((byte >> 6) & 1) + + ((byte >> 5) & 1) + + ((byte >> 4) & 1) + + ((byte >> 3) & 1) + + ((byte >> 2) & 1) + + ((byte >> 1) & 1) + + (byte & 1); +} + +bool oneAtBit(unsigned char byte, int8_t bitIndex) { + return (byte >> (7 - bitIndex) & 1); +} diff --git a/shared/src/SharedUtil.h b/shared/src/SharedUtil.h index e0094e1cf8..352ff1d859 100644 --- a/shared/src/SharedUtil.h +++ b/shared/src/SharedUtil.h @@ -19,7 +19,13 @@ double usecTimestamp(timeval *time); double usecTimestampNow(); + float randFloat(); -void outputBits(char); +unsigned char randomColorValue(uint8_t minimum); +bool randomBoolean(); + +void outputBits(unsigned char byte); +int8_t numberOfOnes(unsigned char byte); +bool oneAtBit(unsigned char byte, int8_t bitIndex); #endif /* defined(__hifi__SharedUtil__) */ From 92fc1ed1a61f217557071c816349d777d6250dbd Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 19 Mar 2013 15:51:48 -0700 Subject: [PATCH 02/21] receive bitstream from voxel server on client --- interface/src/VoxelSystem.cpp | 94 ++++++++++++++++++++--------------- interface/src/VoxelSystem.h | 2 + 2 files changed, 56 insertions(+), 40 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 1bb02b3ce8..abe2e46b50 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -6,9 +6,10 @@ // Copyright (c) 2012 High Fidelity, Inc. All rights reserved. // -#include "VoxelSystem.h" -#include #include +#include +#include +#include "VoxelSystem.h" const int MAX_VOXELS_PER_SYSTEM = 500000; @@ -37,53 +38,66 @@ GLubyte identityIndices[] = { 0,1,2, 0,2,3, VoxelSystem::VoxelSystem() { voxelsRendered = 0; + tree = new VoxelTree(); } VoxelSystem::~VoxelSystem() { delete[] verticesArray; delete[] colorsArray; + delete tree; } void VoxelSystem::parseData(void *data, int size) { - // ignore the first char, it's a V to tell us that this is voxel data - char *voxelDataPtr = (char *) data + 1; + // output the bits received from the voxel server + unsigned char *voxelData = (unsigned char *) data + 1; + + printf("Received a packet of %d bytes from VS\n", size); + + // ask the VoxelTree to read the bitstream into the tree + tree->readBitstreamToTree(voxelData, size - 1); + + // output the VoxelTree data to see if it matches the server + tree->printTreeForDebugging(tree->rootNode); - GLfloat *position = new GLfloat[3]; - GLubyte *color = new GLubyte[3]; - - // get pointers to position of last append of data - GLfloat *parseVerticesPtr = lastAddPointer; - GLubyte *parseColorsPtr = colorsArray + (lastAddPointer - verticesArray); - - int voxelsInData = 0; - - // pull voxels out of the received data and put them into our internal memory structure - while ((voxelDataPtr - (char *) data) < size) { - - memcpy(position, voxelDataPtr, 3 * sizeof(float)); - voxelDataPtr += 3 * sizeof(float); - memcpy(color, voxelDataPtr, 3); - voxelDataPtr += 3; - - for (int v = 0; v < VERTEX_POINTS_PER_VOXEL; v++) { - parseVerticesPtr[v] = position[v % 3] + (identityVertices[v] * CUBE_WIDTH); - } - - parseVerticesPtr += VERTEX_POINTS_PER_VOXEL; - - for (int c = 0; c < COLOR_VALUES_PER_VOXEL; c++) { - parseColorsPtr[c] = color[c % 3]; - } - - parseColorsPtr += COLOR_VALUES_PER_VOXEL; - - - voxelsInData++; - } - - // increase the lastAddPointer to the new spot, increase the number of rendered voxels - lastAddPointer = parseVerticesPtr; - voxelsRendered += voxelsInData; +// // ignore the first char, it's a V to tell us that this is voxel data +// char *voxelDataPtr = (char *) data + 1; +// +// GLfloat *position = new GLfloat[3]; +// GLubyte *color = new GLubyte[3]; +// +// // get pointers to position of last append of data +// GLfloat *parseVerticesPtr = lastAddPointer; +// GLubyte *parseColorsPtr = colorsArray + (lastAddPointer - verticesArray); +// +// int voxelsInData = 0; +// +// // pull voxels out of the received data and put them into our internal memory structure +// while ((voxelDataPtr - (char *) data) < size) { +// +// memcpy(position, voxelDataPtr, 3 * sizeof(float)); +// voxelDataPtr += 3 * sizeof(float); +// memcpy(color, voxelDataPtr, 3); +// voxelDataPtr += 3; +// +// for (int v = 0; v < VERTEX_POINTS_PER_VOXEL; v++) { +// parseVerticesPtr[v] = position[v % 3] + (identityVertices[v] * CUBE_WIDTH); +// } +// +// parseVerticesPtr += VERTEX_POINTS_PER_VOXEL; +// +// for (int c = 0; c < COLOR_VALUES_PER_VOXEL; c++) { +// parseColorsPtr[c] = color[c % 3]; +// } +// +// parseColorsPtr += COLOR_VALUES_PER_VOXEL; +// +// +// voxelsInData++; +// } +// +// // increase the lastAddPointer to the new spot, increase the number of rendered voxels +// lastAddPointer = parseVerticesPtr; +// voxelsRendered += voxelsInData; } VoxelSystem* VoxelSystem::clone() const { diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index ed6359f1bc..7402577a4a 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -14,6 +14,7 @@ #include #include #include +#include #include "Util.h" #include "world.h" @@ -34,6 +35,7 @@ public: int getVoxelsRendered() {return voxelsRendered;}; private: int voxelsRendered; + VoxelTree *tree; GLfloat *verticesArray; GLubyte *colorsArray; GLfloat *lastAddPointer; From 76f7f685265a793ae105224e5dee6976df5611f9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 19 Mar 2013 15:52:51 -0700 Subject: [PATCH 03/21] fix voxel system to send new bistream format, add helpers to VoxelNode class --- shared/src/VoxelNode.cpp | 60 +++++++++ shared/src/VoxelNode.h | 5 + shared/src/VoxelTree.cpp | 260 ++++++++++++++++++++++++++++++--------- shared/src/VoxelTree.h | 8 +- voxel/src/main.cpp | 76 +++++------- 5 files changed, 306 insertions(+), 103 deletions(-) diff --git a/shared/src/VoxelNode.cpp b/shared/src/VoxelNode.cpp index 6bf1cf15b4..62c0756ea2 100644 --- a/shared/src/VoxelNode.cpp +++ b/shared/src/VoxelNode.cpp @@ -6,7 +6,9 @@ // // +#include "SharedUtil.h" #include "VoxelNode.h" +#include "OctalCode.h" VoxelNode::VoxelNode() { @@ -17,4 +19,62 @@ VoxelNode::VoxelNode() { for (int i = 0; i < 8; i++) { children[i] = NULL; } +} + +VoxelNode::~VoxelNode() { + delete[] octalCode; + + // delete all of this node's children + for (int i = 0; i < 8; i++) { + delete children[i]; + } +} + +void VoxelNode::addChildAtIndex(int8_t childIndex) { + children[childIndex] = new VoxelNode(); + + // give this child its octal code + children[childIndex]->octalCode = childOctalCode(octalCode, childIndex); +} + +void VoxelNode::setColorFromAverageOfChildren(int * colorArray) { + if (colorArray == NULL) { + colorArray = new int[4]; + memset(colorArray, 0, 4); + + for (int i = 0; i < 8; i++) { + if (children[i] != NULL && children[i]->color[3] == 1) { + for (int j = 0; j < 3; j++) { + colorArray[j] += children[i]->color[j]; + } + + colorArray[3]++; + } + } + } + + if (colorArray[3] > 4) { + // we need at least 4 colored children to have an average color value + // or if we have none we generate random values + + for (int c = 0; c < 3; c++) { + // set the average color value + color[c] = colorArray[c] / colorArray[3]; + } + + // set the alpha to 1 to indicate that this isn't transparent + color[3] = 1; + } else { + // some children, but not enough + // set this node's alpha to 0 + color[3] = 0; + } +} + +void VoxelNode::setRandomColor(int minimumBrightness) { + for (int c = 0; c < 3; c++) { + color[c] = randomColorValue(minimumBrightness); + } + + color[3] = 1; } \ No newline at end of file diff --git a/shared/src/VoxelNode.h b/shared/src/VoxelNode.h index 383f24e523..4efe7e0dec 100644 --- a/shared/src/VoxelNode.h +++ b/shared/src/VoxelNode.h @@ -14,6 +14,11 @@ class VoxelNode { public: VoxelNode(); + ~VoxelNode(); + + void addChildAtIndex(int8_t childIndex); + void setColorFromAverageOfChildren(int * colorArray = NULL); + void setRandomColor(int minimumBrightness); unsigned char *octalCode; unsigned char color[4]; diff --git a/shared/src/VoxelTree.cpp b/shared/src/VoxelTree.cpp index 8bb57b6989..e858c92c31 100644 --- a/shared/src/VoxelTree.cpp +++ b/shared/src/VoxelTree.cpp @@ -6,6 +6,7 @@ // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // +#include "SharedUtil.h" #include "OctalCode.h" #include "VoxelTree.h" @@ -17,69 +18,180 @@ VoxelTree::VoxelTree() { *rootNode->octalCode = (char)0; } -unsigned char * VoxelTree::loadBitstreamBuffer(char *& bitstreamBuffer, +VoxelTree::~VoxelTree() { + // delete the children of the root node + // this recursively deletes the tree + for (int i = 0; i < 8; i++) { + delete rootNode->children[i]; + } +} + +VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode) { + // find the appropriate branch index based on this ancestorNode + if (*needleCode == 0) { + return ancestorNode; + } else if (ancestorNode->childMask != 0) { + int8_t branchForNeedle = branchIndexWithDescendant(ancestorNode->octalCode, needleCode); + VoxelNode *childNode = ancestorNode->children[branchForNeedle]; + + if (childNode != NULL) { + if (*childNode->octalCode == *needleCode) { + // the fact that the number of sections is equivalent does not always guarantee + // that this is the same node, however due to the recursive traversal + // we know that this is our node + return childNode; + } else { + // we need to go deeper + return nodeForOctalCode(childNode, needleCode); + } + } + } + + // we've been given a code we don't have a node for + // return this node as the last created parent + return ancestorNode; +} + +VoxelNode * VoxelTree::createMissingNode(VoxelNode *lastParentNode, unsigned char *codeToReach) { + uint8_t indexOfNewChild = branchIndexWithDescendant(lastParentNode->octalCode, codeToReach); + lastParentNode->addChildAtIndex(indexOfNewChild); + + if (*lastParentNode->children[indexOfNewChild]->octalCode == *codeToReach) { + return lastParentNode; + } else { + return createMissingNode(lastParentNode->children[indexOfNewChild], codeToReach); + } +} + +int VoxelTree::readNodeData(VoxelNode *destinationNode, unsigned char * nodeData, int bytesLeftToRead) { + + // instantiate variable for bytes already read + int bytesRead = 1; + int colorArray[4] = {}; + + for (int i = 0; i < 8; i++) { + // check the colors mask to see if we have a child to color in + if (oneAtBit(*nodeData, i)) { + printf("Adding child with color at index %d\n", i); + + // create the child if it doesn't exist + if (destinationNode->children[i] == NULL) { + destinationNode->addChildAtIndex(i); + } + + // pull the color for this child + memcpy(destinationNode->children[i]->color, nodeData + bytesRead, 3); + destinationNode->children[i]->color[3] = 1; + + for (int j = 0; j < 3; j++) { + colorArray[j] += destinationNode->children[i]->color[j]; + } + + bytesRead += 3; + colorArray[3]++; + } + } + + // average node's color based on color of children + destinationNode->setColorFromAverageOfChildren(colorArray); + + // give this destination node the child mask from the packet + printf("The child mask is\n"); + outputBits(*(nodeData + bytesRead)); + printf("\n"); + destinationNode->childMask = *(nodeData + bytesRead); + + int childIndex = 0; + bytesRead++; + + while (bytesLeftToRead - bytesRead > 0 && childIndex < 8) { + // check the exists mask to see if we have a child to traverse into + + if (oneAtBit(destinationNode->childMask, childIndex)) { + if (destinationNode->children[childIndex] == NULL) { + // add a child at that index, if it doesn't exist + destinationNode->addChildAtIndex(childIndex); + } + + // tell the child to read the subsequent data + bytesRead += readNodeData(destinationNode->children[childIndex], nodeData + bytesRead, bytesLeftToRead - bytesRead); + } + + childIndex++; + } + + return bytesRead; +} + +void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeBytes) { + VoxelNode *bitstreamRootNode = nodeForOctalCode(rootNode, (unsigned char *)bitstream); + + if (*bitstream != *bitstreamRootNode->octalCode) { + // if the octal code returned is not on the same level as + // the code being searched for, we have VoxelNodes to create + bitstreamRootNode = createMissingNode(bitstreamRootNode, (unsigned char *)bitstream); + } + + int octalCodeBytes = bytesRequiredForCodeLength(*bitstream); + readNodeData(bitstreamRootNode, bitstream + octalCodeBytes, bufferSizeBytes - octalCodeBytes); +} + +unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer, unsigned char * stopOctalCode, VoxelNode *currentVoxelNode) { - static char *initialBitstreamPos = bitstreamBuffer; + static unsigned char *initialBitstreamPos = bitstreamBuffer; - char firstIndexToCheck = 0; + uint8_t firstIndexToCheck = 0; // we'll only be writing data if we're lower than // or at the same level as the stopOctalCode if (*currentVoxelNode->octalCode >= *stopOctalCode) { - if (currentVoxelNode->childMask != 0) { - if ((bitstreamBuffer - initialBitstreamPos) + MAX_TREE_SLICE_BYTES > MAX_VOXEL_PACKET_SIZE) { - // we can't send this packet, not enough room - // return our octal code as the stop - return currentVoxelNode->octalCode; - } - - if (strcmp((char *)stopOctalCode, (char *)currentVoxelNode->octalCode) == 0) { - // this is is the root node for this packet - // add the leading V - *(bitstreamBuffer++) = 'V'; - - // add its octal code to the packet - int octalCodeBytes = bytesRequiredForCodeLength(*currentVoxelNode->octalCode); - - memcpy(bitstreamBuffer, currentVoxelNode->octalCode, octalCodeBytes); - bitstreamBuffer += octalCodeBytes; - } - - // default color mask is 0, increment pointer for colors - *bitstreamBuffer = 0; - - // keep a colorPointer so we can check how many colors were added - char *colorPointer = bitstreamBuffer + 1; - - for (int i = 0; i < 8; i++) { - - // check if the child exists and is not transparent - if (currentVoxelNode->children[i] != NULL - && currentVoxelNode->children[i]->color[3] != 0) { - - // copy in the childs color to bitstreamBuffer - memcpy(colorPointer, currentVoxelNode->children[i]->color, 3); - colorPointer += 3; - - // set the colorMask by bitshifting the value of childExists - *bitstreamBuffer += (1 << (7 - i)); - } - } - - // push the bitstreamBuffer forwards for the number of added colors - bitstreamBuffer += (colorPointer - bitstreamBuffer); - - // copy the childMask to the current position of the bitstreamBuffer - // and push the buffer pointer forwards - - *(bitstreamBuffer++) = currentVoxelNode->childMask; - } else { - // if this node is a leaf, return a NULL stop code - // it has been visited - return NULL; + if ((bitstreamBuffer - initialBitstreamPos) + MAX_TREE_SLICE_BYTES > MAX_VOXEL_PACKET_SIZE) { + // we can't send this packet, not enough room + // return our octal code as the stop + return currentVoxelNode->octalCode; } + + if (strcmp((char *)stopOctalCode, (char *)currentVoxelNode->octalCode) == 0) { + // this is is the root node for this packet + // add the leading V + *(bitstreamBuffer++) = 'V'; + + // add its octal code to the packet + int octalCodeBytes = bytesRequiredForCodeLength(*currentVoxelNode->octalCode); + + memcpy(bitstreamBuffer, currentVoxelNode->octalCode, octalCodeBytes); + bitstreamBuffer += octalCodeBytes; + } + + // default color mask is 0, increment pointer for colors + *bitstreamBuffer = 0; + + // keep a colorPointer so we can check how many colors were added + unsigned char *colorPointer = bitstreamBuffer + 1; + + for (int i = 0; i < 8; i++) { + + // check if the child exists and is not transparent + if (currentVoxelNode->children[i] != NULL + && currentVoxelNode->children[i]->color[3] != 0) { + + // copy in the childs color to bitstreamBuffer + memcpy(colorPointer, currentVoxelNode->children[i]->color, 3); + colorPointer += 3; + + // set the colorMask by bitshifting the value of childExists + *bitstreamBuffer += (1 << (7 - i)); + } + } + + // push the bitstreamBuffer forwards for the number of added colors + bitstreamBuffer += (colorPointer - bitstreamBuffer); + + // copy the childMask to the current position of the bitstreamBuffer + // and push the buffer pointer forwards + *(bitstreamBuffer++) = currentVoxelNode->childMask; } else { firstIndexToCheck = *stopOctalCode > 0 ? branchIndexWithDescendant(currentVoxelNode->octalCode, stopOctalCode) @@ -98,7 +210,11 @@ unsigned char * VoxelTree::loadBitstreamBuffer(char *& bitstreamBuffer, && childStopOctalCode == NULL) { return currentVoxelNode->children[i]->octalCode; } else { - childStopOctalCode = loadBitstreamBuffer(bitstreamBuffer, stopOctalCode, currentVoxelNode->children[i]); + if (oneAtBit(currentVoxelNode->childMask, i)) { + childStopOctalCode = loadBitstreamBuffer(bitstreamBuffer, stopOctalCode, currentVoxelNode->children[i]); + } else { + childStopOctalCode = NULL; + } } } @@ -107,5 +223,37 @@ unsigned char * VoxelTree::loadBitstreamBuffer(char *& bitstreamBuffer, } } - return childStopOctalCode; + return childStopOctalCode; +} + +void VoxelTree::printTreeForDebugging(VoxelNode *startNode) { + uint8_t colorMask = 0; + + // create the color mask + for (int i = 0; i < 8; i++) { + if (startNode->children[i] != NULL && startNode->children[i]->color[3] != 0) { + colorMask += (1 << (7 - i)); + } + } + + outputBits(colorMask); + + // output the colors we have + for (int j = 0; j < 8; j++) { + if (startNode->children[j] != NULL && startNode->children[j]->color[3] != 0) { + for (int c = 0; c < 3; c++) { + outputBits(startNode->children[j]->color[c]); + } + } + } + + outputBits(startNode->childMask); + + // ask children to recursively output their trees + // if they aren't a leaf + for (int k = 0; k < 8; k++) { + if (startNode->children[k] != NULL && oneAtBit(startNode->childMask, k)) { + printTreeForDebugging(startNode->children[k]); + } + } } \ No newline at end of file diff --git a/shared/src/VoxelTree.h b/shared/src/VoxelTree.h index 2bf6aa944e..a7ea8e3275 100644 --- a/shared/src/VoxelTree.h +++ b/shared/src/VoxelTree.h @@ -15,14 +15,20 @@ const int MAX_VOXEL_PACKET_SIZE = 1492; class VoxelTree { + VoxelNode * nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode); + VoxelNode * createMissingNode(VoxelNode *lastParentNode, unsigned char *deepestCodeToCreate); + int readNodeData(VoxelNode *destinationNode, unsigned char * nodeData, int bufferSizeBytes); public: VoxelTree(); + ~VoxelTree(); VoxelNode *rootNode; - unsigned char * loadBitstreamBuffer(char *& bitstreamBuffer, + void readBitstreamToTree(unsigned char * bitstream, int bufferSizeBytes); + unsigned char * loadBitstreamBuffer(unsigned char *& bitstreamBuffer, unsigned char * octalCode, VoxelNode *currentVoxelNode); + void printTreeForDebugging(VoxelNode *startNode); }; diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index beff2abb7f..7c847619e7 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -23,7 +23,7 @@ #include #include #include -#endif _WIN32 +#endif const int VOXEL_LISTEN_PORT = 40106; @@ -46,19 +46,11 @@ char DOMAIN_HOSTNAME[] = "highfidelity.below92.com"; char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup const int DOMAINSERVER_PORT = 40102; -const int MAX_VOXEL_TREE_DEPTH_LEVELS = 5; +const int MAX_VOXEL_TREE_DEPTH_LEVELS = 2; AgentList agentList(VOXEL_LISTEN_PORT); in_addr_t localAddress; -unsigned char randomColorValue() { - return MIN_BRIGHTNESS + (rand() % (255 - MIN_BRIGHTNESS)); -} - -bool randomBoolean() { - return rand() % 2; -} - void *reportAliveToDS(void *args) { timeval lastSend; @@ -82,14 +74,14 @@ void *reportAliveToDS(void *args) { } } -void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { +int randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { // randomly generate children for this node // the first level of the tree (where levelsToGo = MAX_VOXEL_TREE_DEPTH_LEVELS) has all 8 if (levelsToGo > 0) { - int coloredChildren = 0; + int grandChildrenFromNode = 0; bool createdChildren = false; - unsigned char sumColor[3] = {}; + int colorArray[4] = {}; createdChildren = false; @@ -102,51 +94,39 @@ void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { currentRootNode->children[i]->octalCode = childOctalCode(currentRootNode->octalCode, i); // fill out the lower levels of the tree using that node as the root node - randomlyFillVoxelTree(levelsToGo - 1, currentRootNode->children[i]); + grandChildrenFromNode = randomlyFillVoxelTree(levelsToGo - 1, currentRootNode->children[i]); - if (currentRootNode->children[i]) { + if (currentRootNode->children[i]->color[3] == 1) { for (int c = 0; c < 3; c++) { - sumColor[c] += currentRootNode->children[i]->color[c]; + colorArray[c] += currentRootNode->children[i]->color[c]; } - coloredChildren++; + colorArray[3]++; + } + + if (grandChildrenFromNode > 0) { + currentRootNode->childMask += (1 << (7 - i)); } - currentRootNode->childMask += (1 << (7 - i)); createdChildren = true; } } - // figure out the color value for this node - - if (coloredChildren > 4 || !createdChildren) { - // we need at least 4 colored children to have an average color value - // or if we have none we generate random values - - for (int c = 0; c < 3; c++) { - if (coloredChildren > 4) { - // set the average color value - currentRootNode->color[c] = sumColor[c] / coloredChildren; - } else { - // we have no children, we're a leaf - // generate a random color value - currentRootNode->color[c] = randomColorValue(); - } - } - - // set the alpha to 1 to indicate that this isn't transparent - currentRootNode->color[3] = 1; + if (!createdChildren) { + // we didn't create any children for this node, making it a leaf + // give it a random color + currentRootNode->setRandomColor(MIN_BRIGHTNESS); } else { - // some children, but not enough - // set this node's alpha to 0 - currentRootNode->color[3] = 0; + // set the color value for this node + currentRootNode->setColorFromAverageOfChildren(colorArray); } + + return createdChildren; } else { // this is a leaf node, just give it a color - currentRootNode->color[0] = randomColorValue(); - currentRootNode->color[1] = randomColorValue(); - currentRootNode->color[2] = randomColorValue(); - currentRootNode->color[3] = 1; + currentRootNode->setRandomColor(MIN_BRIGHTNESS); + + return 0; } } @@ -196,8 +176,8 @@ int main(int argc, const char * argv[]) // octal codes to the tree nodes that it is creating randomlyFillVoxelTree(MAX_VOXEL_TREE_DEPTH_LEVELS, randomTree.rootNode); - char *voxelPacket = new char[MAX_VOXEL_PACKET_SIZE]; - char *voxelPacketEnd; + unsigned char *voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE]; + unsigned char *voxelPacketEnd; unsigned char *stopOctal; int packetCount; @@ -218,6 +198,10 @@ int main(int argc, const char * argv[]) voxelPacketEnd = voxelPacket; stopOctal = randomTree.loadBitstreamBuffer(voxelPacketEnd, stopOctal, randomTree.rootNode); + agentList.getAgentSocket().send((sockaddr *)&agentPublicAddress, + voxelPacket, + voxelPacketEnd - voxelPacket); + printf("Packet %d sent to agent at address %s is %ld bytes\n", ++packetCount, inet_ntoa(agentPublicAddress.sin_addr), From adb45c825b9bbe527481749931bbb9d2fa76096b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 13:24:18 -0700 Subject: [PATCH 04/21] add method to return the start vertex for an octal code --- shared/src/OctalCode.cpp | 14 ++++++++++++++ shared/src/OctalCode.h | 1 + 2 files changed, 15 insertions(+) diff --git a/shared/src/OctalCode.cpp b/shared/src/OctalCode.cpp index 9a53e7cfb5..9535402f77 100644 --- a/shared/src/OctalCode.cpp +++ b/shared/src/OctalCode.cpp @@ -102,3 +102,17 @@ unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber return newCode; } + +float * firstVertexForCode(unsigned char * octalCode) { + float * firstVertex = new float[3]; + memset(firstVertex, 0, 3 * sizeof(float)); + + for (int i = 0; i < numberOfThreeBitSectionsInCode(octalCode); i++) { + int8_t sectionIndex = sectionValue(octalCode + 1 + (3 * i / 8), (3 * i) % 8); + for (int j = 0; j < 3; j++) { + firstVertex[j] += 0.5 * (int)oneAtBit(sectionIndex, 7 -j); + } + } + + return firstVertex; +} diff --git a/shared/src/OctalCode.h b/shared/src/OctalCode.h index b66dcc7199..a292116a75 100644 --- a/shared/src/OctalCode.h +++ b/shared/src/OctalCode.h @@ -16,5 +16,6 @@ int bytesRequiredForCodeLength(unsigned char threeBitCodes); bool isDirectParentOfChild(unsigned char *parentOctalCode, unsigned char * childOctalCode); char branchIndexWithDescendant(unsigned char * ancestorOctalCode, unsigned char * descendantOctalCode); unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber); +float * firstVertexForCode(unsigned char * octalCode); #endif /* defined(__hifi__OctalCode__) */ From 65e9626e724dc16d54bc64ea9f3197dca40f12c2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 13:24:43 -0700 Subject: [PATCH 05/21] remove superfluous debugging --- shared/src/VoxelTree.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/shared/src/VoxelTree.cpp b/shared/src/VoxelTree.cpp index e858c92c31..4efaaac9c2 100644 --- a/shared/src/VoxelTree.cpp +++ b/shared/src/VoxelTree.cpp @@ -96,9 +96,6 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode, unsigned char * nodeData destinationNode->setColorFromAverageOfChildren(colorArray); // give this destination node the child mask from the packet - printf("The child mask is\n"); - outputBits(*(nodeData + bytesRead)); - printf("\n"); destinationNode->childMask = *(nodeData + bytesRead); int childIndex = 0; From 634e9c4bf7da10bf113dd6a1cf307ca058ff0cc6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 13:25:11 -0700 Subject: [PATCH 06/21] parse the bitstream tree and create an in memory representation to render --- interface/src/VoxelSystem.cpp | 135 ++++++++++++++++------------------ interface/src/VoxelSystem.h | 6 +- 2 files changed, 68 insertions(+), 73 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index abe2e46b50..c7a2e37270 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -7,33 +7,32 @@ // #include +#include #include +#include #include #include "VoxelSystem.h" -const int MAX_VOXELS_PER_SYSTEM = 500000; +const int MAX_VOXELS_PER_SYSTEM = 250000; const int VERTICES_PER_VOXEL = 8; const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; -const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; const int INDICES_PER_VOXEL = 3 * 12; -const float CUBE_WIDTH = 0.025f; - -float identityVertices[] = { -1, -1, 1, - 1, -1, 1, - 1, -1, -1, - -1, -1, -1, +float identityVertices[] = { 0, 0, 0, + 1, 0, 0, + 1, 1, 0, + 0, 1, 0, + 0, 0, 1, + 1, 0, 1, 1, 1, 1, - -1, 1, 1, - -1, 1, -1, - 1, 1, -1 }; + 0, 1, 1 }; GLubyte identityIndices[] = { 0,1,2, 0,2,3, - 0,4,1, 0,4,5, - 0,3,6, 0,5,6, - 1,2,4, 2,4,7, - 2,3,6, 2,6,7, + 0,1,5, 0,4,5, + 0,3,7, 0,4,7, + 1,2,6, 1,5,6, + 2,3,7, 2,6,7, 4,5,6, 4,6,7 }; VoxelSystem::VoxelSystem() { @@ -56,48 +55,48 @@ void VoxelSystem::parseData(void *data, int size) { // ask the VoxelTree to read the bitstream into the tree tree->readBitstreamToTree(voxelData, size - 1); - // output the VoxelTree data to see if it matches the server - tree->printTreeForDebugging(tree->rootNode); + // reset the verticesEndPointer so we're writing to the beginning of the array + verticesEndPointer = verticesArray; + + // call recursive function to populate in memory arrays + // it will return the number of voxels added + voxelsRendered = treeToArrays(tree->rootNode); + + // set the boolean if there are any voxels to be rendered so we re-fill the VBOs + voxelsToRender = (voxelsRendered > 0); +} -// // ignore the first char, it's a V to tell us that this is voxel data -// char *voxelDataPtr = (char *) data + 1; -// -// GLfloat *position = new GLfloat[3]; -// GLubyte *color = new GLubyte[3]; -// -// // get pointers to position of last append of data -// GLfloat *parseVerticesPtr = lastAddPointer; -// GLubyte *parseColorsPtr = colorsArray + (lastAddPointer - verticesArray); -// -// int voxelsInData = 0; -// -// // pull voxels out of the received data and put them into our internal memory structure -// while ((voxelDataPtr - (char *) data) < size) { -// -// memcpy(position, voxelDataPtr, 3 * sizeof(float)); -// voxelDataPtr += 3 * sizeof(float); -// memcpy(color, voxelDataPtr, 3); -// voxelDataPtr += 3; -// -// for (int v = 0; v < VERTEX_POINTS_PER_VOXEL; v++) { -// parseVerticesPtr[v] = position[v % 3] + (identityVertices[v] * CUBE_WIDTH); -// } -// -// parseVerticesPtr += VERTEX_POINTS_PER_VOXEL; -// -// for (int c = 0; c < COLOR_VALUES_PER_VOXEL; c++) { -// parseColorsPtr[c] = color[c % 3]; -// } -// -// parseColorsPtr += COLOR_VALUES_PER_VOXEL; -// -// -// voxelsInData++; -// } -// -// // increase the lastAddPointer to the new spot, increase the number of rendered voxels -// lastAddPointer = parseVerticesPtr; -// voxelsRendered += voxelsInData; +int VoxelSystem::treeToArrays(VoxelNode *currentNode) { + int voxelsAdded = 0; + + for (int i = 0; i < 8; i++) { + // check if there is a child here + if (currentNode->children[i] != NULL) { + voxelsAdded += treeToArrays(currentNode->children[i]); + } + } + + // if we didn't get any voxels added then we're a leaf + // add our vertex and color information to the interleaved array + if (voxelsAdded == 0) { + float * startVertex = firstVertexForCode(currentNode->octalCode); + float voxelScale = 1 / powf(2, *currentNode->octalCode); + + printf("Adding a voxel at %f, %f, %f\n", startVertex[0], startVertex[1], startVertex[2]); + + // populate the array with points for the 8 vertices + // and RGB color for each added vertex + for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { + *verticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); + *(colorsArray + (verticesEndPointer - verticesArray)) = currentNode->color[j % 3]; + + verticesEndPointer++; + } + + voxelsAdded++; + } + + return voxelsAdded; } VoxelSystem* VoxelSystem::clone() const { @@ -107,8 +106,8 @@ VoxelSystem* VoxelSystem::clone() const { void VoxelSystem::init() { // prep the data structures for incoming voxel data - lastDrawPointer = lastAddPointer = verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; - colorsArray = new GLubyte[COLOR_VALUES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; + verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; + colorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; @@ -134,7 +133,7 @@ void VoxelSystem::init() { // VBO for colorsArray glGenBuffers(1, &vboColorsID); glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); - glBufferData(GL_ARRAY_BUFFER, COLOR_VALUES_PER_VOXEL * sizeof(GLubyte) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); // VBO for the indicesArray glGenBuffers(1, &vboIndicesID); @@ -146,23 +145,17 @@ void VoxelSystem::init() { } void VoxelSystem::render() { - // check if there are new voxels to draw - int vertexValuesToDraw = lastAddPointer - lastDrawPointer; - if (vertexValuesToDraw > 0) { - // calculate the offset into each VBO, in vertex point values - int vertexBufferOffset = lastDrawPointer - verticesArray; - - // bind the vertices VBO, copy in new data + if (voxelsToRender) { glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); - glBufferSubData(GL_ARRAY_BUFFER, vertexBufferOffset * sizeof(GLfloat), vertexValuesToDraw * sizeof(GLfloat), lastDrawPointer); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, (verticesEndPointer - verticesArray) * sizeof(GLfloat), verticesArray); - // bind the colors VBO, copy in new data glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); - glBufferSubData(GL_ARRAY_BUFFER, vertexBufferOffset * sizeof(GLubyte), vertexValuesToDraw * sizeof(GLubyte), (colorsArray + (lastDrawPointer - verticesArray))); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, (verticesEndPointer - verticesArray) * sizeof(GLubyte), colorsArray); - // increment the lastDrawPointer to the lastAddPointer value used for this draw - lastDrawPointer += vertexValuesToDraw; + voxelsToRender = false; } // tell OpenGL where to find vertex and color information diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 7402577a4a..e13ca27b3e 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -36,13 +36,15 @@ public: private: int voxelsRendered; VoxelTree *tree; + bool voxelsToRender; GLfloat *verticesArray; GLubyte *colorsArray; - GLfloat *lastAddPointer; - GLfloat *lastDrawPointer; + GLfloat *verticesEndPointer; GLuint vboVerticesID; GLuint vboColorsID; GLuint vboIndicesID; + + int treeToArrays(VoxelNode *currentNode); }; #endif From 68765c5a2cfddac88000f250e93ce86a07361d43 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 13:27:27 -0700 Subject: [PATCH 07/21] mixer and voxel server must report EC2 address --- mixer/src/main.cpp | 4 ++-- voxel/src/main.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mixer/src/main.cpp b/mixer/src/main.cpp index b0c4566f33..b8f1663537 100644 --- a/mixer/src/main.cpp +++ b/mixer/src/main.cpp @@ -241,8 +241,8 @@ void *reportAliveToDS(void *args) { gettimeofday(&lastSend, NULL); *output = 'M'; -// packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT)); - packSocket(output + 1, 788637888, htons(MIXER_LISTEN_PORT)); + packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT)); +// packSocket(output + 1, 788637888, htons(MIXER_LISTEN_PORT)); agentList.getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7); double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend)); diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index 7c847619e7..9ed3d37a73 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -60,8 +60,8 @@ void *reportAliveToDS(void *args) { gettimeofday(&lastSend, NULL); *output = 'V'; -// packSocket(output + 1, 895283510, htons(VOXEL_LISTEN_PORT)); - packSocket(output + 1, 788637888, htons(VOXEL_LISTEN_PORT)); + packSocket(output + 1, 895283510, htons(VOXEL_LISTEN_PORT)); +// packSocket(output + 1, 788637888, htons(VOXEL_LISTEN_PORT)); agentList.getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7); double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend)); From b24353957ceb918d4d3128f069224dda0669cd30 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 13:29:10 -0700 Subject: [PATCH 08/21] include cstdio for printf in SharedUtil --- shared/src/SharedUtil.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/src/SharedUtil.cpp b/shared/src/SharedUtil.cpp index 404ac9d5cb..e151ca9609 100644 --- a/shared/src/SharedUtil.cpp +++ b/shared/src/SharedUtil.cpp @@ -6,9 +6,9 @@ // // -#include "SharedUtil.h" #include -#include +#include +#include "SharedUtil.h" double usecTimestamp(timeval *time) { return (time->tv_sec * 1000000.0 + time->tv_usec); From 9ac664dbabaf6fa7cf946108ca943b6a279a46bc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 13:34:53 -0700 Subject: [PATCH 09/21] include cstdio for uint8_t --- shared/src/SharedUtil.cpp | 1 - shared/src/SharedUtil.h | 1 + voxel/src/main.cpp | 6 +----- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/shared/src/SharedUtil.cpp b/shared/src/SharedUtil.cpp index e151ca9609..54b1c75e4f 100644 --- a/shared/src/SharedUtil.cpp +++ b/shared/src/SharedUtil.cpp @@ -24,7 +24,6 @@ float randFloat () { return (rand() % 10000)/10000.f; } - unsigned char randomColorValue(uint8_t miniumum) { return miniumum + (rand() % (255 - miniumum)); } diff --git a/shared/src/SharedUtil.h b/shared/src/SharedUtil.h index 352ff1d859..c7f8261070 100644 --- a/shared/src/SharedUtil.h +++ b/shared/src/SharedUtil.h @@ -10,6 +10,7 @@ #define __hifi__SharedUtil__ #include +#include #ifdef _WIN32 #include "Systime.h" diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index 9ed3d37a73..bb43dc80fd 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -27,10 +27,6 @@ const int VOXEL_LISTEN_PORT = 40106; -const int NUMBER_OF_VOXELS = 250000; - -const float MAX_UNIT_ANY_AXIS = 20.0f; - const int VERTICES_PER_VOXEL = 8; const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; @@ -46,7 +42,7 @@ char DOMAIN_HOSTNAME[] = "highfidelity.below92.com"; char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup const int DOMAINSERVER_PORT = 40102; -const int MAX_VOXEL_TREE_DEPTH_LEVELS = 2; +const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4; AgentList agentList(VOXEL_LISTEN_PORT); in_addr_t localAddress; From 1abce2831095ba09a7a92cef44edf8d380ac1ecb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 13:44:09 -0700 Subject: [PATCH 10/21] use int instead of forced 8-bit types where appropriate --- shared/src/OctalCode.cpp | 2 +- shared/src/SharedUtil.cpp | 6 +++--- shared/src/SharedUtil.h | 6 +++--- shared/src/VoxelNode.cpp | 2 +- shared/src/VoxelNode.h | 2 +- shared/src/VoxelTree.cpp | 8 ++++---- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/shared/src/OctalCode.cpp b/shared/src/OctalCode.cpp index 9535402f77..8ba41ea0d9 100644 --- a/shared/src/OctalCode.cpp +++ b/shared/src/OctalCode.cpp @@ -108,7 +108,7 @@ float * firstVertexForCode(unsigned char * octalCode) { memset(firstVertex, 0, 3 * sizeof(float)); for (int i = 0; i < numberOfThreeBitSectionsInCode(octalCode); i++) { - int8_t sectionIndex = sectionValue(octalCode + 1 + (3 * i / 8), (3 * i) % 8); + int sectionIndex = sectionValue(octalCode + 1 + (3 * i / 8), (3 * i) % 8); for (int j = 0; j < 3; j++) { firstVertex[j] += 0.5 * (int)oneAtBit(sectionIndex, 7 -j); } diff --git a/shared/src/SharedUtil.cpp b/shared/src/SharedUtil.cpp index 54b1c75e4f..04e517fe9a 100644 --- a/shared/src/SharedUtil.cpp +++ b/shared/src/SharedUtil.cpp @@ -24,7 +24,7 @@ float randFloat () { return (rand() % 10000)/10000.f; } -unsigned char randomColorValue(uint8_t miniumum) { +unsigned char randomColorValue(int miniumum) { return miniumum + (rand() % (255 - miniumum)); } @@ -42,7 +42,7 @@ void outputBits(unsigned char byte) { printf("\n"); } -int8_t numberOfOnes(unsigned char byte) { +int numberOfOnes(unsigned char byte) { return (byte >> 7) + ((byte >> 6) & 1) + ((byte >> 5) & 1) @@ -53,6 +53,6 @@ int8_t numberOfOnes(unsigned char byte) { + (byte & 1); } -bool oneAtBit(unsigned char byte, int8_t bitIndex) { +bool oneAtBit(unsigned char byte, int bitIndex) { return (byte >> (7 - bitIndex) & 1); } diff --git a/shared/src/SharedUtil.h b/shared/src/SharedUtil.h index c7f8261070..967d0e9786 100644 --- a/shared/src/SharedUtil.h +++ b/shared/src/SharedUtil.h @@ -22,11 +22,11 @@ double usecTimestamp(timeval *time); double usecTimestampNow(); float randFloat(); -unsigned char randomColorValue(uint8_t minimum); +unsigned char randomColorValue(int minimum); bool randomBoolean(); void outputBits(unsigned char byte); -int8_t numberOfOnes(unsigned char byte); -bool oneAtBit(unsigned char byte, int8_t bitIndex); +int numberOfOnes(unsigned char byte); +bool oneAtBit(unsigned char byte, int bitIndex); #endif /* defined(__hifi__SharedUtil__) */ diff --git a/shared/src/VoxelNode.cpp b/shared/src/VoxelNode.cpp index 62c0756ea2..32b86ff2b6 100644 --- a/shared/src/VoxelNode.cpp +++ b/shared/src/VoxelNode.cpp @@ -30,7 +30,7 @@ VoxelNode::~VoxelNode() { } } -void VoxelNode::addChildAtIndex(int8_t childIndex) { +void VoxelNode::addChildAtIndex(int childIndex) { children[childIndex] = new VoxelNode(); // give this child its octal code diff --git a/shared/src/VoxelNode.h b/shared/src/VoxelNode.h index 4efe7e0dec..bdd7428f6d 100644 --- a/shared/src/VoxelNode.h +++ b/shared/src/VoxelNode.h @@ -16,7 +16,7 @@ public: VoxelNode(); ~VoxelNode(); - void addChildAtIndex(int8_t childIndex); + void addChildAtIndex(int childIndex); void setColorFromAverageOfChildren(int * colorArray = NULL); void setRandomColor(int minimumBrightness); diff --git a/shared/src/VoxelTree.cpp b/shared/src/VoxelTree.cpp index 4efaaac9c2..83d0eaa067 100644 --- a/shared/src/VoxelTree.cpp +++ b/shared/src/VoxelTree.cpp @@ -31,7 +31,7 @@ VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * if (*needleCode == 0) { return ancestorNode; } else if (ancestorNode->childMask != 0) { - int8_t branchForNeedle = branchIndexWithDescendant(ancestorNode->octalCode, needleCode); + int branchForNeedle = branchIndexWithDescendant(ancestorNode->octalCode, needleCode); VoxelNode *childNode = ancestorNode->children[branchForNeedle]; if (childNode != NULL) { @@ -53,7 +53,7 @@ VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * } VoxelNode * VoxelTree::createMissingNode(VoxelNode *lastParentNode, unsigned char *codeToReach) { - uint8_t indexOfNewChild = branchIndexWithDescendant(lastParentNode->octalCode, codeToReach); + int indexOfNewChild = branchIndexWithDescendant(lastParentNode->octalCode, codeToReach); lastParentNode->addChildAtIndex(indexOfNewChild); if (*lastParentNode->children[indexOfNewChild]->octalCode == *codeToReach) { @@ -139,7 +139,7 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer, { static unsigned char *initialBitstreamPos = bitstreamBuffer; - uint8_t firstIndexToCheck = 0; + int firstIndexToCheck = 0; // we'll only be writing data if we're lower than // or at the same level as the stopOctalCode @@ -224,7 +224,7 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer, } void VoxelTree::printTreeForDebugging(VoxelNode *startNode) { - uint8_t colorMask = 0; + int colorMask = 0; // create the color mask for (int i = 0; i < 8; i++) { From 6ce4ed2d40a54ea428df788766d91d11b42f8921 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 13:45:48 -0700 Subject: [PATCH 11/21] add cstring for use of memcpy --- shared/src/VoxelTree.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/src/VoxelTree.cpp b/shared/src/VoxelTree.cpp index 83d0eaa067..b78ad591bb 100644 --- a/shared/src/VoxelTree.cpp +++ b/shared/src/VoxelTree.cpp @@ -6,6 +6,7 @@ // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // +#include #include "SharedUtil.h" #include "OctalCode.h" #include "VoxelTree.h" From c28a3e1bd4ddb8c8f8598dfc3ae071fc2a1e9393 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 13:47:13 -0700 Subject: [PATCH 12/21] add cstring for use of memcpy --- shared/src/OctalCode.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/src/OctalCode.cpp b/shared/src/OctalCode.cpp index 8ba41ea0d9..2bb5766e36 100644 --- a/shared/src/OctalCode.cpp +++ b/shared/src/OctalCode.cpp @@ -7,6 +7,7 @@ // #include +#include #include "SharedUtil.h" #include "OctalCode.h" From fc3a499cb376e292009876e0d4404d2e7347837a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 13:48:59 -0700 Subject: [PATCH 13/21] include cstring for use of memset --- shared/src/VoxelNode.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/src/VoxelNode.cpp b/shared/src/VoxelNode.cpp index 32b86ff2b6..87c2b362a2 100644 --- a/shared/src/VoxelNode.cpp +++ b/shared/src/VoxelNode.cpp @@ -6,6 +6,7 @@ // // +#include #include "SharedUtil.h" #include "VoxelNode.h" #include "OctalCode.h" From e8f84aee78766da983ed39202a6778cd548f44c7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 15:32:12 -0700 Subject: [PATCH 14/21] fix rendering bugs --- interface/src/VoxelSystem.cpp | 5 +++-- shared/src/OctalCode.cpp | 9 +++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index c7a2e37270..c7f710e340 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -82,8 +82,6 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode) { float * startVertex = firstVertexForCode(currentNode->octalCode); float voxelScale = 1 / powf(2, *currentNode->octalCode); - printf("Adding a voxel at %f, %f, %f\n", startVertex[0], startVertex[1], startVertex[2]); - // populate the array with points for the 8 vertices // and RGB color for each added vertex for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { @@ -93,6 +91,8 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode) { verticesEndPointer++; } + delete [] startVertex; + voxelsAdded++; } @@ -170,6 +170,7 @@ void VoxelSystem::render() { // draw the number of voxels we have glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); + glScalef(10, 10, 10); glDrawElements(GL_TRIANGLES, 36 * voxelsRendered, GL_UNSIGNED_INT, 0); // deactivate vertex and color arrays after drawing diff --git a/shared/src/OctalCode.cpp b/shared/src/OctalCode.cpp index 2bb5766e36..6beb09d132 100644 --- a/shared/src/OctalCode.cpp +++ b/shared/src/OctalCode.cpp @@ -20,7 +20,7 @@ int numberOfThreeBitSectionsInCode(unsigned char * octalCode) { } void printOctalCode(unsigned char * octalCode) { - for (int i = 1; i < bytesRequiredForCodeLength(*octalCode); i++) { + for (int i = 0; i < bytesRequiredForCodeLength(*octalCode); i++) { outputBits(octalCode[i]); } } @@ -108,11 +108,16 @@ float * firstVertexForCode(unsigned char * octalCode) { float * firstVertex = new float[3]; memset(firstVertex, 0, 3 * sizeof(float)); + float currentScale = 0.5; + for (int i = 0; i < numberOfThreeBitSectionsInCode(octalCode); i++) { int sectionIndex = sectionValue(octalCode + 1 + (3 * i / 8), (3 * i) % 8); + for (int j = 0; j < 3; j++) { - firstVertex[j] += 0.5 * (int)oneAtBit(sectionIndex, 7 -j); + firstVertex[j] += currentScale * (int)oneAtBit(sectionIndex, 5 + j); } + + currentScale *= 0.5; } return firstVertex; From d2da9000f40abe791ec23bf91cf0c23a4340fd93 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 16:21:22 -0700 Subject: [PATCH 15/21] return correct nodeForOctalCode --- shared/src/VoxelTree.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shared/src/VoxelTree.cpp b/shared/src/VoxelTree.cpp index b78ad591bb..bde83ec067 100644 --- a/shared/src/VoxelTree.cpp +++ b/shared/src/VoxelTree.cpp @@ -31,7 +31,7 @@ VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * // find the appropriate branch index based on this ancestorNode if (*needleCode == 0) { return ancestorNode; - } else if (ancestorNode->childMask != 0) { + } else { int branchForNeedle = branchIndexWithDescendant(ancestorNode->octalCode, needleCode); VoxelNode *childNode = ancestorNode->children[branchForNeedle]; @@ -73,7 +73,6 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode, unsigned char * nodeData for (int i = 0; i < 8; i++) { // check the colors mask to see if we have a child to color in if (oneAtBit(*nodeData, i)) { - printf("Adding child with color at index %d\n", i); // create the child if it doesn't exist if (destinationNode->children[i] == NULL) { From 1efbaef44b16a051f6036b617ffe0ea4216f81a1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 16:21:45 -0700 Subject: [PATCH 16/21] only add voxel to be drawn if not transparent --- interface/src/VoxelSystem.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index c7f710e340..4e71270c03 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -82,18 +82,20 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode) { float * startVertex = firstVertexForCode(currentNode->octalCode); float voxelScale = 1 / powf(2, *currentNode->octalCode); - // populate the array with points for the 8 vertices - // and RGB color for each added vertex - for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { - *verticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); - *(colorsArray + (verticesEndPointer - verticesArray)) = currentNode->color[j % 3]; + if (currentNode->color[3] == 1) { + // populate the array with points for the 8 vertices + // and RGB color for each added vertex + for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { + *verticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); + *(colorsArray + (verticesEndPointer - verticesArray)) = currentNode->color[j % 3]; + + verticesEndPointer++; + } - verticesEndPointer++; + voxelsAdded++; } - + delete [] startVertex; - - voxelsAdded++; } return voxelsAdded; From e7254ff2169a047bdaf0c886e3ae4d6e3b7fb975 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 16:22:01 -0700 Subject: [PATCH 17/21] fix shift in return of octal code section value --- shared/src/OctalCode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/src/OctalCode.cpp b/shared/src/OctalCode.cpp index 6beb09d132..3b22879b75 100644 --- a/shared/src/OctalCode.cpp +++ b/shared/src/OctalCode.cpp @@ -29,7 +29,7 @@ char sectionValue(unsigned char * startByte, char startIndexInByte) { char rightShift = 8 - startIndexInByte - 3; if (rightShift < 0) { - return ((startByte[0] << -rightShift) & 7) + (startByte[1] >> 7); + return ((startByte[0] << -rightShift) & 7) + (startByte[1] >> (8 + rightShift)); } else { return (startByte[0] >> rightShift) & 7; } From abc0deaa78d84cb1b3076e80969fee5dd1f6d691 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 16:22:24 -0700 Subject: [PATCH 18/21] increase the far clip --- interface/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 9c4209be1d..b8ef6b71db 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -828,7 +828,7 @@ void reshape(int width, int height) gluPerspective(45, //view angle 1.0, //aspect ratio 0.1, //near clip - 50.0);//far clip + 500.0);//far clip glMatrixMode(GL_MODELVIEW); glLoadIdentity(); From f4e9594f72edd997d63e6c32b7fa630f19acf5fc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 16:22:38 -0700 Subject: [PATCH 19/21] dumb way to keep voxel server alive for testing --- shared/src/AgentList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/src/AgentList.cpp b/shared/src/AgentList.cpp index ed27f8ea8c..3dba8ea406 100644 --- a/shared/src/AgentList.cpp +++ b/shared/src/AgentList.cpp @@ -233,7 +233,7 @@ void *removeSilentAgents(void *args) { checkTimeUSecs = usecTimestampNow(); for(std::vector::iterator agent = agents->begin(); agent != agents->end();) { - if ((checkTimeUSecs - agent->getLastRecvTimeUsecs()) > AGENT_SILENCE_THRESHOLD_USECS) { + if ((checkTimeUSecs - agent->getLastRecvTimeUsecs()) > AGENT_SILENCE_THRESHOLD_USECS && agent->getType() != 'V') { std::cout << "Killing agent " << &(*agent) << "\n"; pthread_mutex_lock(&vectorChangeMutex); agent = agents->erase(agent); From f8485ab5da89ac65ffc1cd12af3edb97374ab2f7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 16:23:10 -0700 Subject: [PATCH 20/21] output total number of packets and bytes sent to agent from VS --- voxel/src/main.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index bb43dc80fd..bbe4d88890 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -177,6 +177,7 @@ int main(int argc, const char * argv[]) unsigned char *stopOctal; int packetCount; + int totalBytesSent; sockaddr_in agentPublicAddress; @@ -198,11 +199,14 @@ int main(int argc, const char * argv[]) voxelPacket, voxelPacketEnd - voxelPacket); - printf("Packet %d sent to agent at address %s is %ld bytes\n", - ++packetCount, - inet_ntoa(agentPublicAddress.sin_addr), - voxelPacketEnd - voxelPacket); + packetCount++; + totalBytesSent += voxelPacketEnd - voxelPacket; } + + printf("%d packets sent to agent %s totalling %d bytes\n", + packetCount, + inet_ntoa(agentPublicAddress.sin_addr), + totalBytesSent); } } } From f97932353b24bdcaa593db2e8abc409ac4b7f4ff Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 20 Mar 2013 16:28:28 -0700 Subject: [PATCH 21/21] fix conditional inclusion of voxel in vertices and color arrays --- interface/src/VoxelSystem.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 4e71270c03..6a35268521 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -78,22 +78,20 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode) { // if we didn't get any voxels added then we're a leaf // add our vertex and color information to the interleaved array - if (voxelsAdded == 0) { + if (voxelsAdded == 0 && currentNode->color[3] == 1) { float * startVertex = firstVertexForCode(currentNode->octalCode); float voxelScale = 1 / powf(2, *currentNode->octalCode); - if (currentNode->color[3] == 1) { - // populate the array with points for the 8 vertices - // and RGB color for each added vertex - for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { - *verticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); - *(colorsArray + (verticesEndPointer - verticesArray)) = currentNode->color[j % 3]; - - verticesEndPointer++; - } + // populate the array with points for the 8 vertices + // and RGB color for each added vertex + for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { + *verticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); + *(colorsArray + (verticesEndPointer - verticesArray)) = currentNode->color[j % 3]; - voxelsAdded++; + verticesEndPointer++; } + + voxelsAdded++; delete [] startVertex; }