merge with upstream master

This commit is contained in:
Kees van Prooijen 2013-03-21 10:10:33 -07:00
commit f308d8e004
14 changed files with 488 additions and 225 deletions

View file

@ -6,84 +6,97 @@
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved. // Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
// //
#include "VoxelSystem.h"
#include <AgentList.h>
#include <cstring> #include <cstring>
#include <cmath>
#include <SharedUtil.h>
#include <OctalCode.h>
#include <AgentList.h>
#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 VERTICES_PER_VOXEL = 8;
const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; 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 int INDICES_PER_VOXEL = 3 * 12;
const float CUBE_WIDTH = 0.025f; float identityVertices[] = { 0, 0, 0,
1, 0, 0,
float identityVertices[] = { -1, -1, 1, 1, 1, 0,
1, -1, 1, 0, 1, 0,
1, -1, -1, 0, 0, 1,
-1, -1, -1, 1, 0, 1,
1, 1, 1, 1, 1, 1,
-1, 1, 1, 0, 1, 1 };
-1, 1, -1,
1, 1, -1 };
GLubyte identityIndices[] = { 0,1,2, 0,2,3, GLubyte identityIndices[] = { 0,1,2, 0,2,3,
0,4,1, 0,4,5, 0,1,5, 0,4,5,
0,3,6, 0,5,6, 0,3,7, 0,4,7,
1,2,4, 2,4,7, 1,2,6, 1,5,6,
2,3,6, 2,6,7, 2,3,7, 2,6,7,
4,5,6, 4,6,7 }; 4,5,6, 4,6,7 };
VoxelSystem::VoxelSystem() { VoxelSystem::VoxelSystem() {
voxelsRendered = 0; voxelsRendered = 0;
tree = new VoxelTree();
} }
VoxelSystem::~VoxelSystem() { VoxelSystem::~VoxelSystem() {
delete[] verticesArray; delete[] verticesArray;
delete[] colorsArray; delete[] colorsArray;
delete tree;
} }
void VoxelSystem::parseData(void *data, int size) { void VoxelSystem::parseData(void *data, int size) {
// ignore the first char, it's a V to tell us that this is voxel data // output the bits received from the voxel server
char *voxelDataPtr = (char *) data + 1; unsigned char *voxelData = (unsigned 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; printf("Received a packet of %d bytes from VS\n", size);
// pull voxels out of the received data and put them into our internal memory structure // ask the VoxelTree to read the bitstream into the tree
while ((voxelDataPtr - (char *) data) < size) { tree->readBitstreamToTree(voxelData, size - 1);
memcpy(position, voxelDataPtr, 3 * sizeof(float)); // reset the verticesEndPointer so we're writing to the beginning of the array
voxelDataPtr += 3 * sizeof(float); verticesEndPointer = verticesArray;
memcpy(color, voxelDataPtr, 3);
voxelDataPtr += 3; // call recursive function to populate in memory arrays
// it will return the number of voxels added
for (int v = 0; v < VERTEX_POINTS_PER_VOXEL; v++) { voxelsRendered = treeToArrays(tree->rootNode);
parseVerticesPtr[v] = position[v % 3] + (identityVertices[v] * CUBE_WIDTH);
// set the boolean if there are any voxels to be rendered so we re-fill the VBOs
voxelsToRender = (voxelsRendered > 0);
}
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]);
} }
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 // if we didn't get any voxels added then we're a leaf
lastAddPointer = parseVerticesPtr; // add our vertex and color information to the interleaved array
voxelsRendered += voxelsInData; if (voxelsAdded == 0 && currentNode->color[3] == 1) {
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];
verticesEndPointer++;
}
voxelsAdded++;
delete [] startVertex;
}
return voxelsAdded;
} }
VoxelSystem* VoxelSystem::clone() const { VoxelSystem* VoxelSystem::clone() const {
@ -93,8 +106,8 @@ VoxelSystem* VoxelSystem::clone() const {
void VoxelSystem::init() { void VoxelSystem::init() {
// prep the data structures for incoming voxel data // prep the data structures for incoming voxel data
lastDrawPointer = lastAddPointer = verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
colorsArray = new GLubyte[COLOR_VALUES_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]; GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
@ -120,7 +133,7 @@ void VoxelSystem::init() {
// VBO for colorsArray // VBO for colorsArray
glGenBuffers(1, &vboColorsID); glGenBuffers(1, &vboColorsID);
glBindBuffer(GL_ARRAY_BUFFER, 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 // VBO for the indicesArray
glGenBuffers(1, &vboIndicesID); glGenBuffers(1, &vboIndicesID);
@ -132,23 +145,17 @@ void VoxelSystem::init() {
} }
void VoxelSystem::render() { void VoxelSystem::render() {
// check if there are new voxels to draw
int vertexValuesToDraw = lastAddPointer - lastDrawPointer;
if (vertexValuesToDraw > 0) { if (voxelsToRender) {
// calculate the offset into each VBO, in vertex point values
int vertexBufferOffset = lastDrawPointer - verticesArray;
// bind the vertices VBO, copy in new data
glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); 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); 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 voxelsToRender = false;
lastDrawPointer += vertexValuesToDraw;
} }
// tell OpenGL where to find vertex and color information // tell OpenGL where to find vertex and color information
@ -163,6 +170,7 @@ void VoxelSystem::render() {
// draw the number of voxels we have // draw the number of voxels we have
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID);
glScalef(10, 10, 10);
glDrawElements(GL_TRIANGLES, 36 * voxelsRendered, GL_UNSIGNED_INT, 0); glDrawElements(GL_TRIANGLES, 36 * voxelsRendered, GL_UNSIGNED_INT, 0);
// deactivate vertex and color arrays after drawing // deactivate vertex and color arrays after drawing

View file

@ -14,6 +14,7 @@
#include <iostream> #include <iostream>
#include <UDPSocket.h> #include <UDPSocket.h>
#include <AgentData.h> #include <AgentData.h>
#include <VoxelTree.h>
#include "Util.h" #include "Util.h"
#include "world.h" #include "world.h"
@ -34,13 +35,16 @@ public:
int getVoxelsRendered() {return voxelsRendered;}; int getVoxelsRendered() {return voxelsRendered;};
private: private:
int voxelsRendered; int voxelsRendered;
VoxelTree *tree;
bool voxelsToRender;
GLfloat *verticesArray; GLfloat *verticesArray;
GLubyte *colorsArray; GLubyte *colorsArray;
GLfloat *lastAddPointer; GLfloat *verticesEndPointer;
GLfloat *lastDrawPointer;
GLuint vboVerticesID; GLuint vboVerticesID;
GLuint vboColorsID; GLuint vboColorsID;
GLuint vboIndicesID; GLuint vboIndicesID;
int treeToArrays(VoxelNode *currentNode);
}; };
#endif #endif

View file

@ -841,7 +841,7 @@ void reshape(int width, int height)
gluPerspective(45, //view angle gluPerspective(45, //view angle
1.0, //aspect ratio 1.0, //aspect ratio
0.1, //near clip 0.1, //near clip
50.0);//far clip 500.0);//far clip
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();

View file

@ -244,8 +244,8 @@ void *reportAliveToDS(void *args) {
gettimeofday(&lastSend, NULL); gettimeofday(&lastSend, NULL);
*output = 'M'; *output = 'M';
// packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT)); packSocket(output + 1, 895283510, htons(MIXER_LISTEN_PORT));
packSocket(output + 1, 788637888, htons(MIXER_LISTEN_PORT)); // packSocket(output + 1, 788637888, htons(MIXER_LISTEN_PORT));
agentList.getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7); agentList.getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7);
double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend)); double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend));
@ -356,4 +356,4 @@ int main(int argc, const char * argv[])
return 0; return 0;
} }
#endif _WIN32 #endif _WIN32

View file

@ -233,7 +233,7 @@ void *removeSilentAgents(void *args) {
checkTimeUSecs = usecTimestampNow(); checkTimeUSecs = usecTimestampNow();
for(std::vector<Agent>::iterator agent = agents->begin(); agent != agents->end();) { for(std::vector<Agent>::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"; std::cout << "Killing agent " << &(*agent) << "\n";
pthread_mutex_lock(&vectorChangeMutex); pthread_mutex_lock(&vectorChangeMutex);
agent = agents->erase(agent); agent = agents->erase(agent);

View file

@ -7,6 +7,7 @@
// //
#include <cmath> #include <cmath>
#include <cstring>
#include "SharedUtil.h" #include "SharedUtil.h"
#include "OctalCode.h" #include "OctalCode.h"
@ -19,7 +20,7 @@ int numberOfThreeBitSectionsInCode(unsigned char * octalCode) {
} }
void printOctalCode(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]); outputBits(octalCode[i]);
} }
} }
@ -28,7 +29,7 @@ char sectionValue(unsigned char * startByte, char startIndexInByte) {
char rightShift = 8 - startIndexInByte - 3; char rightShift = 8 - startIndexInByte - 3;
if (rightShift < 0) { if (rightShift < 0) {
return ((startByte[0] << -rightShift) & 7) + (startByte[1] >> 7); return ((startByte[0] << -rightShift) & 7) + (startByte[1] >> (8 + rightShift));
} else { } else {
return (startByte[0] >> rightShift) & 7; return (startByte[0] >> rightShift) & 7;
} }
@ -102,3 +103,22 @@ unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber
return newCode; return newCode;
} }
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] += currentScale * (int)oneAtBit(sectionIndex, 5 + j);
}
currentScale *= 0.5;
}
return firstVertex;
}

View file

@ -16,5 +16,6 @@ int bytesRequiredForCodeLength(unsigned char threeBitCodes);
bool isDirectParentOfChild(unsigned char *parentOctalCode, unsigned char * childOctalCode); bool isDirectParentOfChild(unsigned char *parentOctalCode, unsigned char * childOctalCode);
char branchIndexWithDescendant(unsigned char * ancestorOctalCode, unsigned char * descendantOctalCode); char branchIndexWithDescendant(unsigned char * ancestorOctalCode, unsigned char * descendantOctalCode);
unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber); unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber);
float * firstVertexForCode(unsigned char * octalCode);
#endif /* defined(__hifi__OctalCode__) */ #endif /* defined(__hifi__OctalCode__) */

View file

@ -6,9 +6,9 @@
// //
// //
#include "SharedUtil.h"
#include <cstdlib> #include <cstdlib>
#include <bitset> #include <cstdio>
#include "SharedUtil.h"
double usecTimestamp(timeval *time) { double usecTimestamp(timeval *time) {
return (time->tv_sec * 1000000.0 + time->tv_usec); return (time->tv_sec * 1000000.0 + time->tv_usec);
@ -24,7 +24,15 @@ float randFloat () {
return (rand() % 10000)/10000.f; return (rand() % 10000)/10000.f;
} }
void outputBits(char byte) { unsigned char randomColorValue(int miniumum) {
return miniumum + (rand() % (255 - miniumum));
}
bool randomBoolean() {
return rand() % 2;
}
void outputBits(unsigned char byte) {
printf("%d: ", byte); printf("%d: ", byte);
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
@ -32,4 +40,19 @@ void outputBits(char byte) {
} }
printf("\n"); printf("\n");
} }
int 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, int bitIndex) {
return (byte >> (7 - bitIndex) & 1);
}

View file

@ -10,6 +10,7 @@
#define __hifi__SharedUtil__ #define __hifi__SharedUtil__
#include <iostream> #include <iostream>
#include <cstdio>
#ifdef _WIN32 #ifdef _WIN32
#include "Systime.h" #include "Systime.h"
@ -19,7 +20,13 @@
double usecTimestamp(timeval *time); double usecTimestamp(timeval *time);
double usecTimestampNow(); double usecTimestampNow();
float randFloat(); float randFloat();
void outputBits(char); unsigned char randomColorValue(int minimum);
bool randomBoolean();
void outputBits(unsigned char byte);
int numberOfOnes(unsigned char byte);
bool oneAtBit(unsigned char byte, int bitIndex);
#endif /* defined(__hifi__SharedUtil__) */ #endif /* defined(__hifi__SharedUtil__) */

View file

@ -6,7 +6,10 @@
// //
// //
#include <cstring>
#include "SharedUtil.h"
#include "VoxelNode.h" #include "VoxelNode.h"
#include "OctalCode.h"
VoxelNode::VoxelNode() { VoxelNode::VoxelNode() {
@ -17,4 +20,62 @@ VoxelNode::VoxelNode() {
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
children[i] = NULL; 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(int 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;
} }

View file

@ -14,6 +14,11 @@
class VoxelNode { class VoxelNode {
public: public:
VoxelNode(); VoxelNode();
~VoxelNode();
void addChildAtIndex(int childIndex);
void setColorFromAverageOfChildren(int * colorArray = NULL);
void setRandomColor(int minimumBrightness);
unsigned char *octalCode; unsigned char *octalCode;
unsigned char color[4]; unsigned char color[4];

View file

@ -6,6 +6,8 @@
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
// //
#include <cstring>
#include "SharedUtil.h"
#include "OctalCode.h" #include "OctalCode.h"
#include "VoxelTree.h" #include "VoxelTree.h"
@ -17,69 +19,176 @@ VoxelTree::VoxelTree() {
*rootNode->octalCode = (char)0; *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 {
int 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) {
int 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)) {
// 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
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, unsigned char * stopOctalCode,
VoxelNode *currentVoxelNode) VoxelNode *currentVoxelNode)
{ {
static char *initialBitstreamPos = bitstreamBuffer; static unsigned char *initialBitstreamPos = bitstreamBuffer;
char firstIndexToCheck = 0; int firstIndexToCheck = 0;
// we'll only be writing data if we're lower than // we'll only be writing data if we're lower than
// or at the same level as the stopOctalCode // or at the same level as the stopOctalCode
if (*currentVoxelNode->octalCode >= *stopOctalCode) { if (*currentVoxelNode->octalCode >= *stopOctalCode) {
if (currentVoxelNode->childMask != 0) { if ((bitstreamBuffer - initialBitstreamPos) + MAX_TREE_SLICE_BYTES > MAX_VOXEL_PACKET_SIZE) {
if ((bitstreamBuffer - initialBitstreamPos) + MAX_TREE_SLICE_BYTES > MAX_VOXEL_PACKET_SIZE) { // we can't send this packet, not enough room
// we can't send this packet, not enough room // return our octal code as the stop
// return our octal code as the stop return currentVoxelNode->octalCode;
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 (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 { } else {
firstIndexToCheck = *stopOctalCode > 0 firstIndexToCheck = *stopOctalCode > 0
? branchIndexWithDescendant(currentVoxelNode->octalCode, stopOctalCode) ? branchIndexWithDescendant(currentVoxelNode->octalCode, stopOctalCode)
@ -98,7 +207,11 @@ unsigned char * VoxelTree::loadBitstreamBuffer(char *& bitstreamBuffer,
&& childStopOctalCode == NULL) { && childStopOctalCode == NULL) {
return currentVoxelNode->children[i]->octalCode; return currentVoxelNode->children[i]->octalCode;
} else { } 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 +220,37 @@ unsigned char * VoxelTree::loadBitstreamBuffer(char *& bitstreamBuffer,
} }
} }
return childStopOctalCode; return childStopOctalCode;
}
void VoxelTree::printTreeForDebugging(VoxelNode *startNode) {
int 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]);
}
}
} }

View file

@ -15,14 +15,20 @@
const int MAX_VOXEL_PACKET_SIZE = 1492; const int MAX_VOXEL_PACKET_SIZE = 1492;
class VoxelTree { 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: public:
VoxelTree(); VoxelTree();
~VoxelTree();
VoxelNode *rootNode; VoxelNode *rootNode;
unsigned char * loadBitstreamBuffer(char *& bitstreamBuffer, void readBitstreamToTree(unsigned char * bitstream, int bufferSizeBytes);
unsigned char * loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
unsigned char * octalCode, unsigned char * octalCode,
VoxelNode *currentVoxelNode); VoxelNode *currentVoxelNode);
void printTreeForDebugging(VoxelNode *startNode);
}; };

View file

@ -22,15 +22,10 @@
#include <sys/time.h> #include <sys/time.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <ifaddrs.h> #include <ifaddrs.h>
#endif _WIN32 #endif
#include <SharedUtil.h>
const int VOXEL_LISTEN_PORT = 40106; 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 VERTICES_PER_VOXEL = 8;
const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
@ -46,34 +41,26 @@ char DOMAIN_HOSTNAME[] = "highfidelity.below92.com";
char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup
const int DOMAINSERVER_PORT = 40102; const int DOMAINSERVER_PORT = 40102;
const int MAX_VOXEL_TREE_DEPTH_LEVELS = 5; const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
AgentList agentList(VOXEL_LISTEN_PORT); AgentList agentList(VOXEL_LISTEN_PORT);
in_addr_t localAddress; in_addr_t localAddress;
unsigned char randomColorValue() {
return MIN_BRIGHTNESS + (rand() % (255 - MIN_BRIGHTNESS));
}
bool randomBoolean() {
return rand() % 2 != 0;
}
void *reportAliveToDS(void *args) { void *reportAliveToDS(void *args) {
timeval lastSend; timeval lastSend;
unsigned char output[7]; unsigned char output[7];
while (true) { while (true) {
gettimeofday(&lastSend, NULL); gettimeofday(&lastSend, NULL);
*output = 'V'; *output = 'V';
// packSocket(output + 1, 895283510, htons(VOXEL_LISTEN_PORT)); packSocket(output + 1, 895283510, htons(VOXEL_LISTEN_PORT));
packSocket(output + 1, 788637888, htons(VOXEL_LISTEN_PORT)); // packSocket(output + 1, 788637888, htons(VOXEL_LISTEN_PORT));
agentList.getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7); agentList.getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7);
double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend)); double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend));
if (usecToSleep > 0) { if (usecToSleep > 0) {
#ifdef _WIN32 #ifdef _WIN32
Sleep( static_cast<int>(1000.0f*usecToSleep) ); Sleep( static_cast<int>(1000.0f*usecToSleep) );
@ -86,71 +73,59 @@ void *reportAliveToDS(void *args) {
} }
} }
void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) { int randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) {
// randomly generate children for this node // randomly generate children for this node
// the first level of the tree (where levelsToGo = MAX_VOXEL_TREE_DEPTH_LEVELS) has all 8 // the first level of the tree (where levelsToGo = MAX_VOXEL_TREE_DEPTH_LEVELS) has all 8
if (levelsToGo > 0) { if (levelsToGo > 0) {
int coloredChildren = 0; int grandChildrenFromNode = 0;
bool createdChildren = false; bool createdChildren = false;
unsigned char sumColor[3] = {}; int colorArray[4] = {};
createdChildren = false; createdChildren = false;
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
if (randomBoolean() || levelsToGo == MAX_VOXEL_TREE_DEPTH_LEVELS) { if (randomBoolean() || levelsToGo == MAX_VOXEL_TREE_DEPTH_LEVELS) {
// create a new VoxelNode to put here // create a new VoxelNode to put here
currentRootNode->children[i] = new VoxelNode(); currentRootNode->children[i] = new VoxelNode();
// give this child it's octal code // give this child it's octal code
currentRootNode->children[i]->octalCode = childOctalCode(currentRootNode->octalCode, i); currentRootNode->children[i]->octalCode = childOctalCode(currentRootNode->octalCode, i);
// fill out the lower levels of the tree using that node as the root node // 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++) { for (int c = 0; c < 3; c++) {
sumColor[c] += currentRootNode->children[i]->color[c]; colorArray[c] += currentRootNode->children[i]->color[c];
} }
coloredChildren++; colorArray[3]++;
} }
currentRootNode->childMask += (1 << (7 - i)); if (grandChildrenFromNode > 0) {
currentRootNode->childMask += (1 << (7 - i));
}
createdChildren = true; createdChildren = true;
} }
} }
// figure out the color value for this node if (!createdChildren) {
// we didn't create any children for this node, making it a leaf
if (coloredChildren > 4 || !createdChildren) { // give it a random color
// we need at least 4 colored children to have an average color value currentRootNode->setRandomColor(MIN_BRIGHTNESS);
// 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;
} else { } else {
// some children, but not enough // set the color value for this node
// set this node's alpha to 0 currentRootNode->setColorFromAverageOfChildren(colorArray);
currentRootNode->color[3] = 0;
} }
return createdChildren;
} else { } else {
// this is a leaf node, just give it a color // this is a leaf node, just give it a color
currentRootNode->color[0] = randomColorValue(); currentRootNode->setRandomColor(MIN_BRIGHTNESS);
currentRootNode->color[1] = randomColorValue();
currentRootNode->color[2] = randomColorValue(); return 0;
currentRootNode->color[3] = 1;
} }
} }
@ -158,13 +133,13 @@ int main(int argc, const char * argv[])
{ {
setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stdout, NULL, _IOLBF, 0);
#ifndef _WIN32 #ifndef _WIN32
// get the local address of the voxel server // get the local address of the voxel server
struct ifaddrs * ifAddrStruct=NULL; struct ifaddrs * ifAddrStruct=NULL;
struct ifaddrs * ifa=NULL; struct ifaddrs * ifa=NULL;
getifaddrs(&ifAddrStruct); getifaddrs(&ifAddrStruct);
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4 if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4
// is a valid IP4 Address // is a valid IP4 Address
@ -172,7 +147,7 @@ int main(int argc, const char * argv[])
} }
} }
#endif #endif
// Lookup the IP address of things we have hostnames // Lookup the IP address of things we have hostnames
if (atoi(DOMAIN_IP) == 0) { if (atoi(DOMAIN_IP) == 0) {
struct hostent* pHostInfo; struct hostent* pHostInfo;
@ -181,59 +156,67 @@ int main(int argc, const char * argv[])
memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length); memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length);
strcpy(DOMAIN_IP, inet_ntoa(tempAddress.sin_addr)); strcpy(DOMAIN_IP, inet_ntoa(tempAddress.sin_addr));
printf("Domain server %s: %s\n", DOMAIN_HOSTNAME, DOMAIN_IP); printf("Domain server %s: %s\n", DOMAIN_HOSTNAME, DOMAIN_IP);
} else { } else {
printf("Failed lookup domainserver\n"); printf("Failed lookup domainserver\n");
} }
} else { } else {
printf("Using static domainserver IP: %s\n", DOMAIN_IP); printf("Using static domainserver IP: %s\n", DOMAIN_IP);
} }
// setup the agentSocket to report to domain server // setup the agentSocket to report to domain server
pthread_t reportAliveThread; pthread_t reportAliveThread;
pthread_create(&reportAliveThread, NULL, reportAliveToDS, NULL); pthread_create(&reportAliveThread, NULL, reportAliveToDS, NULL);
srand((unsigned)time(0)); srand((unsigned)time(0));
// use our method to create a random voxel tree // use our method to create a random voxel tree
VoxelTree randomTree; VoxelTree randomTree;
// create an octal code buffer and load it with 0 so that the recursive tree fill can give // create an octal code buffer and load it with 0 so that the recursive tree fill can give
// octal codes to the tree nodes that it is creating // octal codes to the tree nodes that it is creating
randomlyFillVoxelTree(MAX_VOXEL_TREE_DEPTH_LEVELS, randomTree.rootNode); randomlyFillVoxelTree(MAX_VOXEL_TREE_DEPTH_LEVELS, randomTree.rootNode);
char *voxelPacket = new char[MAX_VOXEL_PACKET_SIZE]; unsigned char *voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE];
char *voxelPacketEnd; unsigned char *voxelPacketEnd;
unsigned char *stopOctal; unsigned char *stopOctal;
int packetCount; int packetCount;
int totalBytesSent;
sockaddr_in agentPublicAddress; sockaddr_in agentPublicAddress;
char *packetData = new char[MAX_PACKET_SIZE]; char *packetData = new char[MAX_PACKET_SIZE];
ssize_t receivedBytes; ssize_t receivedBytes;
// loop to send to agents requesting data // loop to send to agents requesting data
while (true) { while (true) {
if (agentList.getAgentSocket().receive((sockaddr *)&agentPublicAddress, packetData, &receivedBytes)) { if (agentList.getAgentSocket().receive((sockaddr *)&agentPublicAddress, packetData, &receivedBytes)) {
if (packetData[0] == 'I') { if (packetData[0] == 'I') {
stopOctal = randomTree.rootNode->octalCode; stopOctal = randomTree.rootNode->octalCode;
packetCount = 0; packetCount = 0;
while (stopOctal != NULL) { while (stopOctal != NULL) {
voxelPacketEnd = voxelPacket; voxelPacketEnd = voxelPacket;
stopOctal = randomTree.loadBitstreamBuffer(voxelPacketEnd, stopOctal, randomTree.rootNode); stopOctal = randomTree.loadBitstreamBuffer(voxelPacketEnd, stopOctal, randomTree.rootNode);
printf("Packet %d sent to agent at address %s is %ld bytes\n", agentList.getAgentSocket().send((sockaddr *)&agentPublicAddress,
++packetCount, voxelPacket,
inet_ntoa(agentPublicAddress.sin_addr), voxelPacketEnd - voxelPacket);
voxelPacketEnd - voxelPacket);
packetCount++;
totalBytesSent += voxelPacketEnd - voxelPacket;
} }
printf("%d packets sent to agent %s totalling %d bytes\n",
packetCount,
inet_ntoa(agentPublicAddress.sin_addr),
totalBytesSent);
} }
} }
} }
pthread_join(reportAliveThread, NULL); pthread_join(reportAliveThread, NULL);
return 0; return 0;
} }