Merge pull request #176 from ZappoMan/render_voxels_optimization

Render voxels optimization
This commit is contained in:
Philip Rosedale 2013-05-01 20:52:48 -07:00
commit f78f983e2d
9 changed files with 286 additions and 324 deletions

View file

@ -41,69 +41,53 @@ GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- .
4,5,6, 4,6,7 }; // Z+ . 4,5,6, 4,6,7 }; // Z+ .
VoxelSystem::VoxelSystem() { VoxelSystem::VoxelSystem() {
voxelsRendered = 0; _voxelsInArrays = _voxelsUpdated = 0;
tree = new VoxelTree(); _tree = new VoxelTree();
pthread_mutex_init(&bufferWriteLock, NULL); pthread_mutex_init(&_bufferWriteLock, NULL);
} }
VoxelSystem::~VoxelSystem() { VoxelSystem::~VoxelSystem() {
delete[] readVerticesArray; delete[] _readVerticesArray;
delete[] writeVerticesArray; delete[] _writeVerticesArray;
delete[] readColorsArray; delete[] _readColorsArray;
delete[] writeColorsArray; delete[] _writeColorsArray;
delete tree; delete[] _voxelDirtyArray;
pthread_mutex_destroy(&bufferWriteLock); delete _tree;
pthread_mutex_destroy(&_bufferWriteLock);
} }
//////////////////////////////////////////////////////////////////////////////////////////
// Method: VoxelSystem::loadVoxelsFile()
// Description: Loads HiFidelity encoded Voxels from a binary file. The current file
// format is a stream of single voxels with NO color data. Currently
// colors are set randomly
// Complaints: Brad :)
// To Do: Need to add color data to the file.
void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) { void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
_tree->loadVoxelsFile(fileName, wantColorRandomizer);
tree->loadVoxelsFile(fileName,wantColorRandomizer);
copyWrittenDataToReadArrays(); copyWrittenDataToReadArrays();
} }
//////////////////////////////////////////////////////////////////////////////////////////
// Method: VoxelSystem::createSphere()
// Description: Creates a sphere of voxels in the local system at a given location/radius
// To Do: Move this function someplace better? I put it here because we need a
// mechanism to tell the system to redraw it's arrays after voxels are done
// being added. This is a concept mostly only understood by VoxelSystem.
// Complaints: Brad :)
void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) { void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) {
_tree->createSphere(r, xc, yc, zc, s, solid, wantColorRandomizer);
tree->createSphere(r,xc,yc,zc,s,solid,wantColorRandomizer);
setupNewVoxelsForDrawing(); setupNewVoxelsForDrawing();
} }
long int VoxelSystem::getVoxelsCreated() { long int VoxelSystem::getVoxelsCreated() {
return tree->voxelsCreated; return _tree->voxelsCreated;
} }
float VoxelSystem::getVoxelsCreatedPerSecondAverage() { float VoxelSystem::getVoxelsCreatedPerSecondAverage() {
return (1 / tree->voxelsCreatedStats.getEventDeltaAverage()); return (1 / _tree->voxelsCreatedStats.getEventDeltaAverage());
} }
long int VoxelSystem::getVoxelsColored() { long int VoxelSystem::getVoxelsColored() {
return tree->voxelsColored; return _tree->voxelsColored;
} }
float VoxelSystem::getVoxelsColoredPerSecondAverage() { float VoxelSystem::getVoxelsColoredPerSecondAverage() {
return (1 / tree->voxelsColoredStats.getEventDeltaAverage()); return (1 / _tree->voxelsColoredStats.getEventDeltaAverage());
} }
long int VoxelSystem::getVoxelsBytesRead() { long int VoxelSystem::getVoxelsBytesRead() {
return tree->voxelsBytesRead; return _tree->voxelsBytesRead;
} }
float VoxelSystem::getVoxelsBytesReadPerSecondAverage() { float VoxelSystem::getVoxelsBytesReadPerSecondAverage() {
return tree->voxelsBytesReadStats.getAverageSampleValuePerSecond(); return _tree->voxelsBytesReadStats.getAverageSampleValuePerSecond();
} }
int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
@ -114,11 +98,11 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
switch(command) { switch(command) {
case PACKET_HEADER_VOXEL_DATA: case PACKET_HEADER_VOXEL_DATA:
// ask the VoxelTree to read the bitstream into the tree // ask the VoxelTree to read the bitstream into the tree
tree->readBitstreamToTree(voxelData, numBytes - 1); _tree->readBitstreamToTree(voxelData, numBytes - 1);
break; break;
case PACKET_HEADER_ERASE_VOXEL: case PACKET_HEADER_ERASE_VOXEL:
// ask the tree to read the "remove" bitstream // ask the tree to read the "remove" bitstream
tree->processRemoveVoxelBitstream(sourceBuffer, numBytes); _tree->processRemoveVoxelBitstream(sourceBuffer, numBytes);
break; break;
case PACKET_HEADER_Z_COMMAND: case PACKET_HEADER_Z_COMMAND:
@ -135,7 +119,8 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
while (totalLength <= numBytes) { while (totalLength <= numBytes) {
if (0==strcmp(command,(char*)"erase all")) { if (0==strcmp(command,(char*)"erase all")) {
printLog("got Z message == erase all\n"); printLog("got Z message == erase all\n");
tree->eraseAllVoxels(); _tree->eraseAllVoxels();
_voxelsInArrays = 0; // better way to do this??
} }
if (0==strcmp(command,(char*)"add scene")) { if (0==strcmp(command,(char*)"add scene")) {
printLog("got Z message == add scene - NOT SUPPORTED ON INTERFACE\n"); printLog("got Z message == add scene - NOT SUPPORTED ON INTERFACE\n");
@ -150,78 +135,87 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
} }
void VoxelSystem::setupNewVoxelsForDrawing() { void VoxelSystem::setupNewVoxelsForDrawing() {
// reset the verticesEndPointer so we're writing to the beginning of the array _voxelsUpdated = newTreeToArrays(_tree->rootNode);
writeVerticesEndPointer = writeVerticesArray; if (_voxelsUpdated) {
// call recursive function to populate in memory arrays _voxelsDirty=true;
// it will return the number of voxels added }
glm::vec3 treeRoot = glm::vec3(0,0,0);
voxelsRendered = treeToArrays(tree->rootNode, treeRoot);
// copy the newly written data to the arrays designated for reading // copy the newly written data to the arrays designated for reading
copyWrittenDataToReadArrays(); copyWrittenDataToReadArrays();
} }
void VoxelSystem::copyWrittenDataToReadArrays() { void VoxelSystem::copyWrittenDataToReadArrays() {
// lock on the buffer write lock so we can't modify the data when the GPU is reading it if (_voxelsDirty) {
pthread_mutex_lock(&bufferWriteLock); // lock on the buffer write lock so we can't modify the data when the GPU is reading it
// store a pointer to the current end so it doesn't change during copy pthread_mutex_lock(&_bufferWriteLock);
GLfloat *endOfCurrentVerticesData = writeVerticesEndPointer; int bytesOfVertices = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat);
// copy the vertices and colors int bytesOfColors = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLubyte);
memcpy(readVerticesArray, writeVerticesArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLfloat)); memcpy(_readVerticesArray, _writeVerticesArray, bytesOfVertices);
memcpy(readColorsArray, writeColorsArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLubyte)); memcpy(_readColorsArray, _writeColorsArray, bytesOfColors );
// set the read vertices end pointer to the correct spot so the GPU knows how much to pull pthread_mutex_unlock(&_bufferWriteLock);
readVerticesEndPointer = readVerticesArray + (endOfCurrentVerticesData - writeVerticesArray); }
pthread_mutex_unlock(&bufferWriteLock);
} }
int VoxelSystem::treeToArrays(VoxelNode* currentNode, const glm::vec3& nodePosition) { int VoxelSystem::newTreeToArrays(VoxelNode* node) {
int voxelsAdded = 0; assert(_viewFrustum); // you must set up _viewFrustum before calling this
float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE); int voxelsUpdated = 0;
glm::vec3 viewerPosition = _camera->getPosition(); //_viewerAvatar->getPosition(); float distanceToNode = node->distanceToCamera(*_viewFrustum);
float boundary = boundaryDistanceForRenderLevel(*node->octalCode + 1);
float childBoundary = boundaryDistanceForRenderLevel(*node->octalCode + 2);
bool inBoundary = (distanceToNode <= boundary);
bool inChildBoundary = (distanceToNode <= childBoundary);
bool shouldRender = node->isColored() && ((node->isLeaf() && inChildBoundary) || (inBoundary && !inChildBoundary));
// debug LOD code node->setShouldRender(shouldRender);
glm::vec3 debugNodePosition; // let children figure out their renderness
copyFirstVertexForCode(currentNode->octalCode,(float*)&debugNodePosition); for (int i = 0; i < 8; i++) {
if (node->children[i]) {
float distanceToVoxelCenter = sqrtf(powf(viewerPosition.x - nodePosition[0] - halfUnitForVoxel, 2) + voxelsUpdated += newTreeToArrays(node->children[i]);
powf(viewerPosition.y - nodePosition[1] - halfUnitForVoxel, 2) +
powf(viewerPosition.z - nodePosition[2] - halfUnitForVoxel, 2));
int renderLevel = *currentNode->octalCode + 1;
int boundaryPosition = boundaryDistanceForRenderLevel(renderLevel);
bool alwaysDraw = false; // XXXBHG - temporary debug code. Flip this to true to disable LOD blurring
if (alwaysDraw || distanceToVoxelCenter < boundaryPosition) {
for (int i = 0; i < 8; i++) {
// check if there is a child here
if (currentNode->children[i] != NULL) {
glm::vec3 childNodePosition;
copyFirstVertexForCode(currentNode->children[i]->octalCode,(float*)&childNodePosition);
childNodePosition *= (float)TREE_SCALE; // scale it up
voxelsAdded += treeToArrays(currentNode->children[i], childNodePosition);
}
} }
} }
// Now, if we've changed any attributes (our renderness, our color, etc) then update the Arrays... for us
if (node->isDirty() && (shouldRender || node->isKnownBufferIndex())) {
glm::vec3 startVertex;
float voxelScale = 0;
// If we're should render, use our legit location and scale,
if (node->getShouldRender()) {
copyFirstVertexForCode(node->octalCode, (float*)&startVertex);
voxelScale = (1 / powf(2, *node->octalCode));
} else {
// if we shouldn't render then set out location to some infinitely distant location,
// and our scale as infinitely small
startVertex[0] = startVertex[1] = startVertex[2] = FLT_MAX;
voxelScale = 0;
}
// if we didn't get any voxels added then we're a leaf // If this node has not yet been written to the array, then add it to the end of the array.
// add our vertex and color information to the interleaved array glBufferIndex nodeIndex;
if (voxelsAdded == 0 && currentNode->isColored()) { if (node->isKnownBufferIndex()) {
float startVertex[3]; nodeIndex = node->getBufferIndex();
copyFirstVertexForCode(currentNode->octalCode,(float*)&startVertex); } else {
float voxelScale = 1 / powf(2, *currentNode->octalCode); nodeIndex = _voxelsInArrays;
}
_voxelDirtyArray[nodeIndex] = true;
// populate the array with points for the 8 vertices // populate the array with points for the 8 vertices
// and RGB color for each added vertex // and RGB color for each added vertex
for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) {
*writeVerticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL);
*(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->getColor()[j % 3]; GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL);
*(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale);
writeVerticesEndPointer++; *(writeColorsAt +j) = node->getColor()[j % 3];
} }
voxelsAdded++; if (!node->isKnownBufferIndex()) {
node->setBufferIndex(nodeIndex);
_voxelsInArrays++; // our know vertices in the arrays
}
voxelsUpdated++;
node->clearDirtyBit();
} }
return voxelsUpdated;
return voxelsAdded;
} }
VoxelSystem* VoxelSystem::clone() const { VoxelSystem* VoxelSystem::clone() const {
@ -230,20 +224,30 @@ VoxelSystem* VoxelSystem::clone() const {
} }
void VoxelSystem::init() { void VoxelSystem::init() {
// prep the data structures for incoming voxel data
writeVerticesEndPointer = writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
readVerticesEndPointer = readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; // When we change voxels representations in the arrays, we'll update this
_voxelsDirty = false;
_voxelsInArrays = 0;
// we will track individual dirty sections with this array of bools
_voxelDirtyArray = new bool[MAX_VOXELS_PER_SYSTEM];
memset(_voxelDirtyArray, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool));
// prep the data structures for incoming voxel data
_writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
_readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
_writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
_readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
// populate the indicesArray // populate the indicesArray
// this will not change given new voxels, so we can set it all up now // this will not change given new voxels, so we can set it all up now
for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) { for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) {
// fill the indices array // fill the indices array
int voxelIndexOffset = n * INDICES_PER_VOXEL; int voxelIndexOffset = n * INDICES_PER_VOXEL;
GLuint *currentIndicesPos = indicesArray + voxelIndexOffset; GLuint* currentIndicesPos = indicesArray + voxelIndexOffset;
int startIndex = (n * VERTICES_PER_VOXEL); int startIndex = (n * VERTICES_PER_VOXEL);
for (int i = 0; i < INDICES_PER_VOXEL; i++) { for (int i = 0; i < INDICES_PER_VOXEL; i++) {
@ -252,8 +256,8 @@ void VoxelSystem::init() {
} }
} }
GLfloat *normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
GLfloat *normalsArrayEndPointer = normalsArray; GLfloat* normalsArrayEndPointer = normalsArray;
// populate the normalsArray // populate the normalsArray
for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) { for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) {
@ -263,25 +267,25 @@ void VoxelSystem::init() {
} }
// VBO for the verticesArray // VBO for the verticesArray
glGenBuffers(1, &vboVerticesID); glGenBuffers(1, &_vboVerticesID);
glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW);
// VBO for the normalsArray // VBO for the normalsArray
glGenBuffers(1, &vboNormalsID); glGenBuffers(1, &_vboNormalsID);
glBindBuffer(GL_ARRAY_BUFFER, vboNormalsID); glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID);
glBufferData(GL_ARRAY_BUFFER, glBufferData(GL_ARRAY_BUFFER,
VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM,
normalsArray, GL_STATIC_DRAW); normalsArray, GL_STATIC_DRAW);
// 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, VERTEX_POINTS_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);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, glBufferData(GL_ELEMENT_ARRAY_BUFFER,
INDICES_PER_VOXEL * sizeof(GLuint) * MAX_VOXELS_PER_SYSTEM, INDICES_PER_VOXEL * sizeof(GLuint) * MAX_VOXELS_PER_SYSTEM,
indicesArray, GL_STATIC_DRAW); indicesArray, GL_STATIC_DRAW);
@ -291,45 +295,61 @@ void VoxelSystem::init() {
delete[] normalsArray; delete[] normalsArray;
} }
void VoxelSystem::render() { void VoxelSystem::updateVBOs() {
if (_voxelsDirty) {
glPushMatrix(); glBufferIndex segmentStart = 0;
glBufferIndex segmentEnd = 0;
if (readVerticesEndPointer != readVerticesArray) { bool inSegment = false;
// try to lock on the buffer write for (glBufferIndex i = 0; i < _voxelsInArrays; i++) {
// just avoid pulling new data if it is currently being written if (!inSegment) {
if (pthread_mutex_trylock(&bufferWriteLock) == 0) { if (_voxelDirtyArray[i]) {
segmentStart = i;
glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); inSegment = true;
glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLfloat), readVerticesArray); _voxelDirtyArray[i] = false; // consider us clean!
}
glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); } else {
glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLubyte), readColorsArray); if (!_voxelDirtyArray[i] || (i == (_voxelsInArrays - 1)) ) {
segmentEnd = i;
readVerticesEndPointer = readVerticesArray; inSegment = false;
int segmentLength = (segmentEnd - segmentStart) + 1;
pthread_mutex_unlock(&bufferWriteLock); GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom);
segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
}
}
} }
_voxelsDirty = false;
} }
}
void VoxelSystem::render() {
glPushMatrix();
updateVBOs();
// tell OpenGL where to find vertex and color information // tell OpenGL where to find vertex and color information
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
glVertexPointer(3, GL_FLOAT, 0, 0); glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboNormalsID); glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID);
glNormalPointer(GL_FLOAT, 0, 0); glNormalPointer(GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
// 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); glScalef(10, 10, 10);
glDrawElements(GL_TRIANGLES, 36 * voxelsRendered, GL_UNSIGNED_INT, 0); glDrawElements(GL_TRIANGLES, 36 * _voxelsInArrays, GL_UNSIGNED_INT, 0);
// deactivate vertex and color arrays after drawing // deactivate vertex and color arrays after drawing
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);
@ -344,25 +364,12 @@ void VoxelSystem::render() {
glPopMatrix(); glPopMatrix();
} }
void VoxelSystem::simulate(float deltaTime) {
}
int VoxelSystem::_nodeCount = 0; int VoxelSystem::_nodeCount = 0;
bool VoxelSystem::randomColorOperation(VoxelNode* node, bool down, void* extraData) { bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) {
// we do our operations on the way up!
if (down) {
return true;
}
_nodeCount++; _nodeCount++;
if (node->isColored()) { if (node->isColored()) {
nodeColor newColor = { 0,0,0,1 }; nodeColor newColor = { randomColorValue(150), randomColorValue(150), randomColorValue(150), 1 };
newColor[0] = randomColorValue(150);
newColor[1] = randomColorValue(150);
newColor[1] = randomColorValue(150);
node->setColor(newColor); node->setColor(newColor);
} }
return true; return true;
@ -370,43 +377,26 @@ bool VoxelSystem::randomColorOperation(VoxelNode* node, bool down, void* extraDa
void VoxelSystem::randomizeVoxelColors() { void VoxelSystem::randomizeVoxelColors() {
_nodeCount = 0; _nodeCount = 0;
tree->recurseTreeWithOperation(randomColorOperation); _tree->recurseTreeWithOperation(randomColorOperation);
printLog("setting randomized true color for %d nodes\n",_nodeCount); printLog("setting randomized true color for %d nodes\n", _nodeCount);
setupNewVoxelsForDrawing(); setupNewVoxelsForDrawing();
} }
bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, bool down, void* extraData) { bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, void* extraData) {
// we do our operations on the way up!
if (down) {
return true;
}
_nodeCount++; _nodeCount++;
// always false colorize // always false colorize
unsigned char newR = randomColorValue(150); node->setFalseColor(randomColorValue(150), randomColorValue(150), randomColorValue(150));
unsigned char newG = randomColorValue(150);
unsigned char newB = randomColorValue(150);
node->setFalseColor(newR,newG,newB);
return true; // keep going! return true; // keep going!
} }
void VoxelSystem::falseColorizeRandom() { void VoxelSystem::falseColorizeRandom() {
_nodeCount = 0; _nodeCount = 0;
tree->recurseTreeWithOperation(falseColorizeRandomOperation); _tree->recurseTreeWithOperation(falseColorizeRandomOperation);
printLog("setting randomized false color for %d nodes\n",_nodeCount); printLog("setting randomized false color for %d nodes\n", _nodeCount);
setupNewVoxelsForDrawing(); setupNewVoxelsForDrawing();
} }
bool VoxelSystem::trueColorizeOperation(VoxelNode* node, bool down, void* extraData) { bool VoxelSystem::trueColorizeOperation(VoxelNode* node, void* extraData) {
// we do our operations on the way up!
if (down) {
return true;
}
_nodeCount++; _nodeCount++;
node->setFalseColored(false); node->setFalseColored(false);
return true; return true;
@ -414,90 +404,45 @@ bool VoxelSystem::trueColorizeOperation(VoxelNode* node, bool down, void* extraD
void VoxelSystem::trueColorize() { void VoxelSystem::trueColorize() {
_nodeCount = 0; _nodeCount = 0;
tree->recurseTreeWithOperation(trueColorizeOperation); _tree->recurseTreeWithOperation(trueColorizeOperation);
printLog("setting true color for %d nodes\n",_nodeCount); printLog("setting true color for %d nodes\n", _nodeCount);
setupNewVoxelsForDrawing(); setupNewVoxelsForDrawing();
} }
// Will false colorize voxels that are not in view // Will false colorize voxels that are not in view
bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void* extraData) { bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, void* extraData) {
// we do our operations on the way up!
if (down) {
return true;
}
const ViewFrustum* viewFrustum = (const ViewFrustum*) extraData; const ViewFrustum* viewFrustum = (const ViewFrustum*) extraData;
_nodeCount++; _nodeCount++;
// only do this for truely colored voxels...
if (node->isColored()) { if (node->isColored()) {
// If the voxel is outside of the view frustum, then false color it red
if (!node->isInView(*viewFrustum)) { if (!node->isInView(*viewFrustum)) {
// Out of view voxels are colored RED // Out of view voxels are colored RED
unsigned char newR = 255; node->setFalseColor(255, 0, 0);
unsigned char newG = 0;
unsigned char newB = 0;
node->setFalseColor(newR,newG,newB);
} }
} }
return true; // keep going! return true; // keep going!
} }
void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) { void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) {
_nodeCount = 0; _nodeCount = 0;
tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum); _tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum);
printLog("setting in view false color for %d nodes\n",_nodeCount); printLog("setting in view false color for %d nodes\n", _nodeCount);
setupNewVoxelsForDrawing(); setupNewVoxelsForDrawing();
} }
// Will false colorize voxels based on distance from view // Will false colorize voxels based on distance from view
bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool down, void* extraData) { bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, void* extraData) {
// we do our operations on the way up!
if (down) {
return true;
}
ViewFrustum* viewFrustum = (ViewFrustum*) extraData; ViewFrustum* viewFrustum = (ViewFrustum*) extraData;
// only do this for truly colored voxels...
if (node->isColored()) { if (node->isColored()) {
float distance = node->distanceToCamera(*viewFrustum);
// We need our distance for both up and down
glm::vec3 nodePosition;
float* startVertex = firstVertexForCode(node->octalCode);
nodePosition.x = startVertex[0];
nodePosition.y = startVertex[1];
nodePosition.z = startVertex[2];
delete startVertex;
// scale up the node position
nodePosition = nodePosition*(float)TREE_SCALE;
float halfUnitForVoxel = powf(0.5, *node->octalCode) * (0.5 * TREE_SCALE);
glm::vec3 viewerPosition = viewFrustum->getPosition();
float distance = sqrtf(powf(viewerPosition.x - nodePosition.x - halfUnitForVoxel, 2) +
powf(viewerPosition.y - nodePosition.y - halfUnitForVoxel, 2) +
powf(viewerPosition.z - nodePosition.z - halfUnitForVoxel, 2));
// actually colorize
_nodeCount++; _nodeCount++;
float distanceRatio = (_minDistance == _maxDistance) ? 1 : (distance - _minDistance) / (_maxDistance - _minDistance);
float distanceRatio = (_minDistance==_maxDistance) ? 1 : (distance - _minDistance)/(_maxDistance - _minDistance);
// We want to colorize this in 16 bug chunks of color // We want to colorize this in 16 bug chunks of color
const unsigned char maxColor = 255; const unsigned char maxColor = 255;
const unsigned char colorBands = 16; const unsigned char colorBands = 16;
const unsigned char gradientOver = 128; const unsigned char gradientOver = 128;
unsigned char colorBand = (colorBands*distanceRatio); unsigned char colorBand = (colorBands * distanceRatio);
unsigned char newR = (colorBand*(gradientOver/colorBands))+(maxColor-gradientOver); node->setFalseColor((colorBand * (gradientOver / colorBands)) + (maxColor - gradientOver), 0, 0);
unsigned char newG = 0;
unsigned char newB = 0;
node->setFalseColor(newR,newG,newB);
} }
return true; // keep going! return true; // keep going!
} }
@ -508,44 +453,18 @@ float VoxelSystem::_minDistance = FLT_MAX;
// Helper function will get the distance from view range, would be nice if you could just keep track // Helper function will get the distance from view range, would be nice if you could just keep track
// of this as voxels are created and/or colored... seems like some transform math could do that so // of this as voxels are created and/or colored... seems like some transform math could do that so
// we wouldn't need to do two passes of the tree // we wouldn't need to do two passes of the tree
bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, bool down, void* extraData) { bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, void* extraData) {
// we do our operations on the way up!
if (down) {
return true;
}
ViewFrustum* viewFrustum = (ViewFrustum*) extraData; ViewFrustum* viewFrustum = (ViewFrustum*) extraData;
// only do this for truly colored voxels... // only do this for truly colored voxels...
if (node->isColored()) { if (node->isColored()) {
float distance = node->distanceToCamera(*viewFrustum);
// We need our distance for both up and down // calculate the range of distances
glm::vec3 nodePosition;
float* startVertex = firstVertexForCode(node->octalCode);
nodePosition.x = startVertex[0];
nodePosition.y = startVertex[1];
nodePosition.z = startVertex[2];
delete startVertex;
// scale up the node position
nodePosition = nodePosition*(float)TREE_SCALE;
float halfUnitForVoxel = powf(0.5, *node->octalCode) * (0.5 * TREE_SCALE);
glm::vec3 viewerPosition = viewFrustum->getPosition();
float distance = sqrtf(powf(viewerPosition.x - nodePosition.x - halfUnitForVoxel, 2) +
powf(viewerPosition.y - nodePosition.y - halfUnitForVoxel, 2) +
powf(viewerPosition.z - nodePosition.z - halfUnitForVoxel, 2));
// on way down, calculate the range of distances
if (distance > _maxDistance) { if (distance > _maxDistance) {
_maxDistance = distance; _maxDistance = distance;
} }
if (distance < _minDistance) { if (distance < _minDistance) {
_minDistance = distance; _minDistance = distance;
} }
_nodeCount++; _nodeCount++;
} }
return true; // keep going! return true; // keep going!
@ -553,15 +472,14 @@ bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, bool down,
void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) { void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) {
_nodeCount = 0; _nodeCount = 0;
_maxDistance = 0.0; _maxDistance = 0.0;
_minDistance = FLT_MAX; _minDistance = FLT_MAX;
tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum); _tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum);
printLog("determining distance range for %d nodes\n",_nodeCount); printLog("determining distance range for %d nodes\n", _nodeCount);
_nodeCount = 0; _nodeCount = 0;
_tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum);
tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum); printLog("setting in distance false color for %d nodes\n", _nodeCount);
printLog("setting in distance false color for %d nodes\n",_nodeCount);
setupNewVoxelsForDrawing(); setupNewVoxelsForDrawing();
} }

View file

@ -29,12 +29,16 @@ public:
int parseData(unsigned char* sourceBuffer, int numBytes); int parseData(unsigned char* sourceBuffer, int numBytes);
VoxelSystem* clone() const; VoxelSystem* clone() const;
void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; };
void init(); void init();
void simulate(float deltaTime); void simulate(float deltaTime) { };
void render(); void render();
void setVoxelsRendered(int v) {voxelsRendered = v;};
int getVoxelsRendered() {return voxelsRendered;}; unsigned long getVoxelsUpdated() const {return _voxelsUpdated;};
unsigned long getVoxelsRendered() const {return _voxelsInArrays;};
void setViewerAvatar(Avatar *newViewerAvatar) { _viewerAvatar = newViewerAvatar; }; void setViewerAvatar(Avatar *newViewerAvatar) { _viewerAvatar = newViewerAvatar; };
void setCamera(Camera* newCamera) { _camera = newCamera; }; void setCamera(Camera* newCamera) { _camera = newCamera; };
void loadVoxelsFile(const char* fileName,bool wantColorRandomizer); void loadVoxelsFile(const char* fileName,bool wantColorRandomizer);
@ -57,36 +61,42 @@ public:
private: private:
// Operation functions for tree recursion methods // Operation functions for tree recursion methods
static int _nodeCount; static int _nodeCount;
static bool randomColorOperation(VoxelNode* node, bool down, void* extraData); static bool randomColorOperation(VoxelNode* node, void* extraData);
static bool falseColorizeRandomOperation(VoxelNode* node, bool down, void* extraData); static bool falseColorizeRandomOperation(VoxelNode* node, void* extraData);
static bool trueColorizeOperation(VoxelNode* node, bool down, void* extraData); static bool trueColorizeOperation(VoxelNode* node, void* extraData);
static bool falseColorizeInViewOperation(VoxelNode* node, bool down, void* extraData); static bool falseColorizeInViewOperation(VoxelNode* node, void* extraData);
static bool falseColorizeDistanceFromViewOperation(VoxelNode* node, bool down, void* extraData); static bool falseColorizeDistanceFromViewOperation(VoxelNode* node, void* extraData);
static bool getDistanceFromViewRangeOperation(VoxelNode* node, bool down, void* extraData); static bool getDistanceFromViewRangeOperation(VoxelNode* node, void* extraData);
// these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here // these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here
static float _maxDistance; static float _maxDistance;
static float _minDistance; static float _minDistance;
int voxelsRendered;
Avatar* _viewerAvatar; Avatar* _viewerAvatar;
Camera* _camera; Camera* _camera;
VoxelTree *tree; VoxelTree* _tree;
GLfloat *readVerticesArray; GLfloat* _readVerticesArray;
GLubyte *readColorsArray; GLubyte* _readColorsArray;
GLfloat *readVerticesEndPointer; GLfloat* _writeVerticesArray;
GLfloat *writeVerticesArray; GLubyte* _writeColorsArray;
GLubyte *writeColorsArray; bool* _voxelDirtyArray;
GLfloat *writeVerticesEndPointer; unsigned long _voxelsUpdated;
GLuint vboVerticesID; unsigned long _voxelsInArrays;
GLuint vboNormalsID;
GLuint vboColorsID; GLuint _vboVerticesID;
GLuint vboIndicesID; GLuint _vboNormalsID;
pthread_mutex_t bufferWriteLock; GLuint _vboColorsID;
GLuint _vboIndicesID;
pthread_mutex_t _bufferWriteLock;
int treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosition); ViewFrustum* _viewFrustum;
int newTreeToArrays(VoxelNode *currentNode);
void setupNewVoxelsForDrawing(); void setupNewVoxelsForDrawing();
void copyWrittenDataToReadArrays(); void copyWrittenDataToReadArrays();
void updateVBOs();
bool _voxelsDirty;
}; };
#endif #endif

View file

@ -236,7 +236,7 @@ void displayStats(void)
drawtext(10, statsVerticalOffset + 49, 0.10f, 0, 1.0, 0, stats); drawtext(10, statsVerticalOffset + 49, 0.10f, 0, 1.0, 0, stats);
std::stringstream voxelStats; std::stringstream voxelStats;
voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered(); voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered() << " Updated: " << voxels.getVoxelsUpdated();
drawtext(10, statsVerticalOffset + 70, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); drawtext(10, statsVerticalOffset + 70, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
voxelStats.str(""); voxelStats.str("");
@ -1609,6 +1609,8 @@ void audioMixerUpdate(in_addr_t newMixerAddress, in_port_t newMixerPort) {
int main(int argc, const char * argv[]) int main(int argc, const char * argv[])
{ {
voxels.setViewFrustum(&::viewFrustum);
shared_lib::printLog = & ::printLog; shared_lib::printLog = & ::printLog;
voxels_lib::printLog = & ::printLog; voxels_lib::printLog = & ::printLog;
avatars_lib::printLog = & ::printLog; avatars_lib::printLog = & ::printLog;
@ -1631,7 +1633,7 @@ int main(int argc, const char * argv[])
} }
// Handle Local Domain testing with the --local command line // Handle Local Domain testing with the --local command line
if (cmdOptionExists(argc, argv, "--local")) { if (true || cmdOptionExists(argc, argv, "--local")) {
printLog("Local Domain MODE!\n"); printLog("Local Domain MODE!\n");
int ip = getLocalAddress(); int ip = getLocalAddress();
sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF)); sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));

View file

@ -21,4 +21,7 @@ const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
const int INDICES_PER_VOXEL = 3 * 12; const int INDICES_PER_VOXEL = 3 * 12;
const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
typedef unsigned long int glBufferIndex;
const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX;
#endif #endif

View file

@ -30,6 +30,10 @@ VoxelNode::VoxelNode() {
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
children[i] = NULL; children[i] = NULL;
} }
_glBufferIndex = GLBUFFER_INDEX_UNKNOWN;
_isDirty = true;
_shouldRender = false;
} }
VoxelNode::~VoxelNode() { VoxelNode::~VoxelNode() {
@ -43,6 +47,14 @@ VoxelNode::~VoxelNode() {
} }
} }
void VoxelNode::setShouldRender(bool shouldRender) {
// if shouldRender is changing, then consider ourselves dirty
if (shouldRender != _shouldRender) {
_shouldRender = shouldRender;
_isDirty = true;
}
}
void VoxelNode::getAABox(AABox& box) const { void VoxelNode::getAABox(AABox& box) const {
glm::vec3 corner; glm::vec3 corner;
@ -59,16 +71,19 @@ void VoxelNode::getAABox(AABox& box) const {
} }
void VoxelNode::addChildAtIndex(int childIndex) { void VoxelNode::addChildAtIndex(int childIndex) {
children[childIndex] = new VoxelNode(); if (!children[childIndex]) {
children[childIndex] = new VoxelNode();
// XXXBHG - When the node is constructed, it should be cleanly set up as // XXXBHG - When the node is constructed, it should be cleanly set up as
// true colored, but for some reason, not so much. I've added a a basecamp // true colored, but for some reason, not so much. I've added a a basecamp
// to-do to research this. But for now we'll use belt and suspenders and set // to-do to research this. But for now we'll use belt and suspenders and set
// it to not-false-colored here! // it to not-false-colored here!
children[childIndex]->setFalseColored(false); children[childIndex]->setFalseColored(false);
// give this child its octal code // give this child its octal code
children[childIndex]->octalCode = childOctalCode(octalCode, childIndex); children[childIndex]->octalCode = childOctalCode(octalCode, childIndex);
_isDirty = true;
}
} }
// will average the child colors... // will average the child colors...
@ -104,26 +119,35 @@ void VoxelNode::setColorFromAverageOfChildren() {
// the actual NO_FALSE_COLOR version are inline in the VoxelNode.h // the actual NO_FALSE_COLOR version are inline in the VoxelNode.h
#ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color #ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color
void VoxelNode::setFalseColor(colorPart red, colorPart green, colorPart blue) { void VoxelNode::setFalseColor(colorPart red, colorPart green, colorPart blue) {
_falseColored=true; if (_falseColored != true || _currentColor[0] != red || _currentColor[1] != green || _currentColor[2] != blue) {
_currentColor[0] = red; _falseColored=true;
_currentColor[1] = green; _currentColor[0] = red;
_currentColor[2] = blue; _currentColor[1] = green;
_currentColor[3] = 1; // XXXBHG - False colors are always considered set _currentColor[2] = blue;
_currentColor[3] = 1; // XXXBHG - False colors are always considered set
_isDirty = true;
}
} }
void VoxelNode::setFalseColored(bool isFalseColored) { void VoxelNode::setFalseColored(bool isFalseColored) {
// if we were false colored, and are no longer false colored, then swap back if (_falseColored != isFalseColored) {
if (_falseColored && !isFalseColored) { // if we were false colored, and are no longer false colored, then swap back
memcpy(&_currentColor,&_trueColor,sizeof(nodeColor)); if (_falseColored && !isFalseColored) {
memcpy(&_currentColor,&_trueColor,sizeof(nodeColor));
}
_falseColored = isFalseColored;
_isDirty = true;
} }
_falseColored = isFalseColored;
}; };
void VoxelNode::setColor(const nodeColor& color) { void VoxelNode::setColor(const nodeColor& color) {
memcpy(&_trueColor,&color,sizeof(nodeColor)); if (_trueColor[0] != color[0] || _trueColor[1] != color[1] || _trueColor[2] != color[2]) {
if (!_falseColored) { memcpy(&_trueColor,&color,sizeof(nodeColor));
memcpy(&_currentColor,&color,sizeof(nodeColor)); if (!_falseColored) {
memcpy(&_currentColor,&color,sizeof(nodeColor));
}
_isDirty = true;
} }
} }
#endif #endif
@ -199,7 +223,6 @@ void VoxelNode::printDebugDetails(const char* label) const {
printOctalCode(octalCode); printOctalCode(octalCode);
} }
bool VoxelNode::isInView(const ViewFrustum& viewFrustum) const { bool VoxelNode::isInView(const ViewFrustum& viewFrustum) const {
AABox box; AABox box;
getAABox(box); getAABox(box);

View file

@ -11,6 +11,7 @@
#include "AABox.h" #include "AABox.h"
#include "ViewFrustum.h" #include "ViewFrustum.h"
#include "VoxelConstants.h"
typedef unsigned char colorPart; typedef unsigned char colorPart;
typedef unsigned char nodeColor[4]; typedef unsigned char nodeColor[4];
@ -22,6 +23,9 @@ private:
nodeColor _currentColor; nodeColor _currentColor;
bool _falseColored; bool _falseColored;
#endif #endif
glBufferIndex _glBufferIndex;
bool _isDirty;
bool _shouldRender;
public: public:
VoxelNode(); VoxelNode();
~VoxelNode(); ~VoxelNode();
@ -40,7 +44,14 @@ public:
bool isLeaf() const; bool isLeaf() const;
void getAABox(AABox& box) const; void getAABox(AABox& box) const;
void printDebugDetails(const char* label) const; void printDebugDetails(const char* label) const;
bool isDirty() const { return _isDirty; };
void clearDirtyBit() { _isDirty = false; };
glBufferIndex getBufferIndex() const { return _glBufferIndex; };
bool isKnownBufferIndex() const { return (_glBufferIndex != GLBUFFER_INDEX_UNKNOWN); };
void setBufferIndex(glBufferIndex index) { _glBufferIndex = index; };
void setShouldRender(bool shouldRender);
bool getShouldRender() const { return _shouldRender; }
#ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color #ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color
void setFalseColor(colorPart red, colorPart green, colorPart blue); void setFalseColor(colorPart red, colorPart green, colorPart blue);
void setFalseColored(bool isFalseColored); void setFalseColored(bool isFalseColored);

View file

@ -58,16 +58,13 @@ void VoxelTree::recurseTreeWithOperation(RecurseVoxelTreeOperation operation, vo
// Recurses voxel node with an operation function // Recurses voxel node with an operation function
void VoxelTree::recurseNodeWithOperation(VoxelNode* node,RecurseVoxelTreeOperation operation, void* extraData) { void VoxelTree::recurseNodeWithOperation(VoxelNode* node,RecurseVoxelTreeOperation operation, void* extraData) {
// call the operation function going "down" first, stop deeper recursion if function returns false if (operation(node, extraData)) {
if (operation(node,true,extraData)) { for (int i = 0; i < sizeof(node->children) / sizeof(node->children[0]); i++) {
for (int i = 0; i < sizeof(node->children)/sizeof(node->children[0]); i++) {
VoxelNode* child = node->children[i]; VoxelNode* child = node->children[i];
if (child) { if (child) {
recurseNodeWithOperation(child,operation,extraData); recurseNodeWithOperation(child, operation, extraData);
} }
} }
// call operation on way back up
operation(node,false,extraData);
} }
} }

View file

@ -16,7 +16,7 @@
#include "VoxelNodeBag.h" #include "VoxelNodeBag.h"
// Callback function, for recuseTreeWithOperation // Callback function, for recuseTreeWithOperation
typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, bool down, void* extraData); typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, void* extraData);
class VoxelTree { class VoxelTree {
public: public:

View file

@ -38,7 +38,7 @@ const float DEATH_STAR_RADIUS = 4.0;
const float MAX_CUBE = 0.05f; const float MAX_CUBE = 0.05f;
const int VOXEL_SEND_INTERVAL_USECS = 100 * 1000; const int VOXEL_SEND_INTERVAL_USECS = 100 * 1000;
const int PACKETS_PER_CLIENT_PER_INTERVAL = 2; const int PACKETS_PER_CLIENT_PER_INTERVAL = 20;
const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4; const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
@ -68,11 +68,9 @@ void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) {
} }
int _nodeCount=0; int _nodeCount=0;
bool countVoxelsOperation(VoxelNode* node, bool down, void* extraData) { bool countVoxelsOperation(VoxelNode* node, void* extraData) {
if (down) { if (node->isColored()){
if (node->isColored()){ _nodeCount++;
_nodeCount++;
}
} }
return true; // keep going return true; // keep going
} }
@ -80,7 +78,7 @@ bool countVoxelsOperation(VoxelNode* node, bool down, void* extraData) {
void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) { void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) {
printf("adding scene of spheres...\n"); printf("adding scene of spheres...\n");
int sphereBaseSize = 256; int sphereBaseSize = 512;
tree->createSphere(0.25, 0.5, 0.5, 0.5, (1.0 / sphereBaseSize), true, wantColorRandomizer); tree->createSphere(0.25, 0.5, 0.5, 0.5, (1.0 / sphereBaseSize), true, wantColorRandomizer);
printf("one sphere added...\n"); printf("one sphere added...\n");