mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 21:15:07 +02:00
merge with upstream master
This commit is contained in:
commit
f308d8e004
14 changed files with 488 additions and 225 deletions
|
@ -6,84 +6,97 @@
|
|||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "VoxelSystem.h"
|
||||
#include <AgentList.h>
|
||||
#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 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() {
|
||||
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;
|
||||
|
||||
GLfloat *position = new GLfloat[3];
|
||||
GLubyte *color = new GLubyte[3];
|
||||
printf("Received a packet of %d bytes from VS\n", size);
|
||||
|
||||
// get pointers to position of last append of data
|
||||
GLfloat *parseVerticesPtr = lastAddPointer;
|
||||
GLubyte *parseColorsPtr = colorsArray + (lastAddPointer - verticesArray);
|
||||
// ask the VoxelTree to read the bitstream into the tree
|
||||
tree->readBitstreamToTree(voxelData, size - 1);
|
||||
|
||||
int voxelsInData = 0;
|
||||
// reset the verticesEndPointer so we're writing to the beginning of the array
|
||||
verticesEndPointer = verticesArray;
|
||||
|
||||
// pull voxels out of the received data and put them into our internal memory structure
|
||||
while ((voxelDataPtr - (char *) data) < size) {
|
||||
// call recursive function to populate in memory arrays
|
||||
// it will return the number of voxels added
|
||||
voxelsRendered = treeToArrays(tree->rootNode);
|
||||
|
||||
memcpy(position, voxelDataPtr, 3 * sizeof(float));
|
||||
voxelDataPtr += 3 * sizeof(float);
|
||||
memcpy(color, voxelDataPtr, 3);
|
||||
voxelDataPtr += 3;
|
||||
// set the boolean if there are any voxels to be rendered so we re-fill the VBOs
|
||||
voxelsToRender = (voxelsRendered > 0);
|
||||
}
|
||||
|
||||
for (int v = 0; v < VERTEX_POINTS_PER_VOXEL; v++) {
|
||||
parseVerticesPtr[v] = position[v % 3] + (identityVertices[v] * CUBE_WIDTH);
|
||||
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;
|
||||
// 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 && currentNode->color[3] == 1) {
|
||||
float * startVertex = firstVertexForCode(currentNode->octalCode);
|
||||
float voxelScale = 1 / powf(2, *currentNode->octalCode);
|
||||
|
||||
for (int c = 0; c < COLOR_VALUES_PER_VOXEL; c++) {
|
||||
parseColorsPtr[c] = color[c % 3];
|
||||
// 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++;
|
||||
}
|
||||
|
||||
parseColorsPtr += COLOR_VALUES_PER_VOXEL;
|
||||
voxelsAdded++;
|
||||
|
||||
|
||||
voxelsInData++;
|
||||
delete [] startVertex;
|
||||
}
|
||||
|
||||
// increase the lastAddPointer to the new spot, increase the number of rendered voxels
|
||||
lastAddPointer = parseVerticesPtr;
|
||||
voxelsRendered += voxelsInData;
|
||||
return voxelsAdded;
|
||||
}
|
||||
|
||||
VoxelSystem* VoxelSystem::clone() const {
|
||||
|
@ -93,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];
|
||||
|
||||
|
@ -120,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);
|
||||
|
@ -132,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
|
||||
|
@ -163,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
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <iostream>
|
||||
#include <UDPSocket.h>
|
||||
#include <AgentData.h>
|
||||
#include <VoxelTree.h>
|
||||
#include "Util.h"
|
||||
#include "world.h"
|
||||
|
||||
|
@ -34,13 +35,16 @@ public:
|
|||
int getVoxelsRendered() {return voxelsRendered;};
|
||||
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
|
||||
|
|
|
@ -841,7 +841,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();
|
||||
|
||||
|
|
|
@ -244,8 +244,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));
|
||||
|
|
|
@ -233,7 +233,7 @@ void *removeSilentAgents(void *args) {
|
|||
checkTimeUSecs = usecTimestampNow();
|
||||
|
||||
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";
|
||||
pthread_mutex_lock(&vectorChangeMutex);
|
||||
agent = agents->erase(agent);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include "SharedUtil.h"
|
||||
#include "OctalCode.h"
|
||||
|
||||
|
@ -19,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]);
|
||||
}
|
||||
}
|
||||
|
@ -28,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;
|
||||
}
|
||||
|
@ -102,3 +103,22 @@ 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));
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
//
|
||||
//
|
||||
|
||||
#include "SharedUtil.h"
|
||||
#include <cstdlib>
|
||||
#include <bitset>
|
||||
#include <cstdio>
|
||||
#include "SharedUtil.h"
|
||||
|
||||
double usecTimestamp(timeval *time) {
|
||||
return (time->tv_sec * 1000000.0 + time->tv_usec);
|
||||
|
@ -24,7 +24,15 @@ float randFloat () {
|
|||
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);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
|
@ -33,3 +41,18 @@ void outputBits(char byte) {
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#define __hifi__SharedUtil__
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Systime.h"
|
||||
|
@ -19,7 +20,13 @@
|
|||
|
||||
double usecTimestamp(timeval *time);
|
||||
double usecTimestampNow();
|
||||
|
||||
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__) */
|
||||
|
|
|
@ -6,7 +6,10 @@
|
|||
//
|
||||
//
|
||||
|
||||
#include <cstring>
|
||||
#include "SharedUtil.h"
|
||||
#include "VoxelNode.h"
|
||||
#include "OctalCode.h"
|
||||
|
||||
VoxelNode::VoxelNode() {
|
||||
|
||||
|
@ -18,3 +21,61 @@ VoxelNode::VoxelNode() {
|
|||
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;
|
||||
}
|
|
@ -14,6 +14,11 @@
|
|||
class VoxelNode {
|
||||
public:
|
||||
VoxelNode();
|
||||
~VoxelNode();
|
||||
|
||||
void addChildAtIndex(int childIndex);
|
||||
void setColorFromAverageOfChildren(int * colorArray = NULL);
|
||||
void setRandomColor(int minimumBrightness);
|
||||
|
||||
unsigned char *octalCode;
|
||||
unsigned char color[4];
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <cstring>
|
||||
#include "SharedUtil.h"
|
||||
#include "OctalCode.h"
|
||||
#include "VoxelTree.h"
|
||||
|
||||
|
@ -17,18 +19,131 @@ 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 {
|
||||
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,
|
||||
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
|
||||
// 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
|
||||
|
@ -51,7 +166,7 @@ unsigned char * VoxelTree::loadBitstreamBuffer(char *& bitstreamBuffer,
|
|||
*bitstreamBuffer = 0;
|
||||
|
||||
// keep a colorPointer so we can check how many colors were added
|
||||
char *colorPointer = bitstreamBuffer + 1;
|
||||
unsigned char *colorPointer = bitstreamBuffer + 1;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
|
||||
|
@ -73,13 +188,7 @@ unsigned char * VoxelTree::loadBitstreamBuffer(char *& 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;
|
||||
}
|
||||
} else {
|
||||
firstIndexToCheck = *stopOctalCode > 0
|
||||
? branchIndexWithDescendant(currentVoxelNode->octalCode, stopOctalCode)
|
||||
|
@ -98,7 +207,11 @@ unsigned char * VoxelTree::loadBitstreamBuffer(char *& bitstreamBuffer,
|
|||
&& childStopOctalCode == NULL) {
|
||||
return currentVoxelNode->children[i]->octalCode;
|
||||
} else {
|
||||
if (oneAtBit(currentVoxelNode->childMask, i)) {
|
||||
childStopOctalCode = loadBitstreamBuffer(bitstreamBuffer, stopOctalCode, currentVoxelNode->children[i]);
|
||||
} else {
|
||||
childStopOctalCode = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,3 +222,35 @@ unsigned char * VoxelTree::loadBitstreamBuffer(char *& bitstreamBuffer,
|
|||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -22,15 +22,10 @@
|
|||
#include <sys/time.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ifaddrs.h>
|
||||
#endif _WIN32
|
||||
#include <SharedUtil.h>
|
||||
#endif
|
||||
|
||||
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,19 +41,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 = 4;
|
||||
|
||||
AgentList agentList(VOXEL_LISTEN_PORT);
|
||||
in_addr_t localAddress;
|
||||
|
||||
unsigned char randomColorValue() {
|
||||
return MIN_BRIGHTNESS + (rand() % (255 - MIN_BRIGHTNESS));
|
||||
}
|
||||
|
||||
bool randomBoolean() {
|
||||
return rand() % 2 != 0;
|
||||
}
|
||||
|
||||
void *reportAliveToDS(void *args) {
|
||||
|
||||
timeval lastSend;
|
||||
|
@ -68,8 +55,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));
|
||||
|
@ -86,14 +73,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;
|
||||
|
||||
|
@ -106,51 +93,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));
|
||||
}
|
||||
|
||||
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;
|
||||
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 {
|
||||
// we have no children, we're a leaf
|
||||
// generate a random color value
|
||||
currentRootNode->color[c] = randomColorValue();
|
||||
}
|
||||
// set the color value for this node
|
||||
currentRootNode->setColorFromAverageOfChildren(colorArray);
|
||||
}
|
||||
|
||||
// set the alpha to 1 to indicate that this isn't transparent
|
||||
currentRootNode->color[3] = 1;
|
||||
} else {
|
||||
// some children, but not enough
|
||||
// set this node's alpha to 0
|
||||
currentRootNode->color[3] = 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,11 +177,12 @@ 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;
|
||||
int totalBytesSent;
|
||||
|
||||
sockaddr_in agentPublicAddress;
|
||||
|
||||
|
@ -224,11 +200,18 @@ int main(int argc, const char * argv[])
|
|||
voxelPacketEnd = voxelPacket;
|
||||
stopOctal = randomTree.loadBitstreamBuffer(voxelPacketEnd, stopOctal, randomTree.rootNode);
|
||||
|
||||
printf("Packet %d sent to agent at address %s is %ld bytes\n",
|
||||
++packetCount,
|
||||
inet_ntoa(agentPublicAddress.sin_addr),
|
||||
agentList.getAgentSocket().send((sockaddr *)&agentPublicAddress,
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue