From 4f86b5570f283fad2eafe127bc30639bd3dab469 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 1 May 2013 18:21:13 -0700 Subject: [PATCH 1/6] first cut at improved render pipeline --- diff.out | 941 ++++++++++++++++++++++++++ interface/src/VoxelSystem.cpp | 349 +++++----- interface/src/VoxelSystem.h | 54 +- interface/src/main.cpp | 6 +- libraries/voxels/src/VoxelConstants.h | 3 + libraries/voxels/src/VoxelNode.cpp | 65 +- libraries/voxels/src/VoxelNode.h | 18 + libraries/voxels/src/VoxelTree.cpp | 9 +- libraries/voxels/src/VoxelTree.h | 2 +- voxel-server/src/main.cpp | 12 +- 10 files changed, 1222 insertions(+), 237 deletions(-) create mode 100644 diff.out diff --git a/diff.out b/diff.out new file mode 100644 index 0000000000..5acd0ea285 --- /dev/null +++ b/diff.out @@ -0,0 +1,941 @@ +diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp +index 24f7665..b8157d0 100644 +--- a/interface/src/VoxelSystem.cpp ++++ b/interface/src/VoxelSystem.cpp +@@ -41,69 +41,53 @@ GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- . + 4,5,6, 4,6,7 }; // Z+ . + + VoxelSystem::VoxelSystem() { +- voxelsRendered = 0; +- tree = new VoxelTree(); +- pthread_mutex_init(&bufferWriteLock, NULL); ++ _voxelsInArrays = _voxelsUpdated = 0; ++ _tree = new VoxelTree(); ++ pthread_mutex_init(&_bufferWriteLock, NULL); + } + + VoxelSystem::~VoxelSystem() { +- delete[] readVerticesArray; +- delete[] writeVerticesArray; +- delete[] readColorsArray; +- delete[] writeColorsArray; +- delete tree; +- pthread_mutex_destroy(&bufferWriteLock); ++ delete[] _readVerticesArray; ++ delete[] _writeVerticesArray; ++ delete[] _readColorsArray; ++ delete[] _writeColorsArray; ++ delete[] _voxelDirtyArray; ++ 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) { +- +- tree->loadVoxelsFile(fileName,wantColorRandomizer); +- ++ _tree->loadVoxelsFile(fileName, wantColorRandomizer); + 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) { +- +- tree->createSphere(r,xc,yc,zc,s,solid,wantColorRandomizer); ++ _tree->createSphere(r, xc, yc, zc, s, solid, wantColorRandomizer); + setupNewVoxelsForDrawing(); + } + + long int VoxelSystem::getVoxelsCreated() { +- return tree->voxelsCreated; ++ return _tree->voxelsCreated; + } + + float VoxelSystem::getVoxelsCreatedPerSecondAverage() { +- return (1 / tree->voxelsCreatedStats.getEventDeltaAverage()); ++ return (1 / _tree->voxelsCreatedStats.getEventDeltaAverage()); + } + + long int VoxelSystem::getVoxelsColored() { +- return tree->voxelsColored; ++ return _tree->voxelsColored; + } + + float VoxelSystem::getVoxelsColoredPerSecondAverage() { +- return (1 / tree->voxelsColoredStats.getEventDeltaAverage()); ++ return (1 / _tree->voxelsColoredStats.getEventDeltaAverage()); + } + + long int VoxelSystem::getVoxelsBytesRead() { +- return tree->voxelsBytesRead; ++ return _tree->voxelsBytesRead; + } + + float VoxelSystem::getVoxelsBytesReadPerSecondAverage() { +- return tree->voxelsBytesReadStats.getAverageSampleValuePerSecond(); ++ return _tree->voxelsBytesReadStats.getAverageSampleValuePerSecond(); + } + + int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { +@@ -114,11 +98,11 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { + switch(command) { + case PACKET_HEADER_VOXEL_DATA: + // ask the VoxelTree to read the bitstream into the tree +- tree->readBitstreamToTree(voxelData, numBytes - 1); ++ _tree->readBitstreamToTree(voxelData, numBytes - 1); + break; + case PACKET_HEADER_ERASE_VOXEL: + // ask the tree to read the "remove" bitstream +- tree->processRemoveVoxelBitstream(sourceBuffer, numBytes); ++ _tree->processRemoveVoxelBitstream(sourceBuffer, numBytes); + break; + case PACKET_HEADER_Z_COMMAND: + +@@ -135,7 +119,8 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { + while (totalLength <= numBytes) { + if (0==strcmp(command,(char*)"erase all")) { + 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")) { + 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() { +- // reset the verticesEndPointer so we're writing to the beginning of the array +- writeVerticesEndPointer = writeVerticesArray; +- // call recursive function to populate in memory arrays +- // it will return the number of voxels added +- glm::vec3 treeRoot = glm::vec3(0,0,0); +- voxelsRendered = treeToArrays(tree->rootNode, treeRoot); ++ _voxelsUpdated = newTreeToArrays(_tree->rootNode); ++ if (_voxelsUpdated) { ++ _voxelsDirty=true; ++ } ++ + // copy the newly written data to the arrays designated for reading + copyWrittenDataToReadArrays(); + } + + void VoxelSystem::copyWrittenDataToReadArrays() { +- // lock on the buffer write lock so we can't modify the data when the GPU is reading it +- pthread_mutex_lock(&bufferWriteLock); +- // store a pointer to the current end so it doesn't change during copy +- GLfloat *endOfCurrentVerticesData = writeVerticesEndPointer; +- // copy the vertices and colors +- memcpy(readVerticesArray, writeVerticesArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLfloat)); +- memcpy(readColorsArray, writeColorsArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLubyte)); +- // set the read vertices end pointer to the correct spot so the GPU knows how much to pull +- readVerticesEndPointer = readVerticesArray + (endOfCurrentVerticesData - writeVerticesArray); +- pthread_mutex_unlock(&bufferWriteLock); ++ if (_voxelsDirty) { ++ // lock on the buffer write lock so we can't modify the data when the GPU is reading it ++ pthread_mutex_lock(&_bufferWriteLock); ++ int bytesOfVertices = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat); ++ int bytesOfColors = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLubyte); ++ memcpy(_readVerticesArray, _writeVerticesArray, bytesOfVertices); ++ memcpy(_readColorsArray, _writeColorsArray, bytesOfColors ); ++ pthread_mutex_unlock(&_bufferWriteLock); ++ } + } + +-int VoxelSystem::treeToArrays(VoxelNode* currentNode, const glm::vec3& nodePosition) { +- int voxelsAdded = 0; +- float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE); +- glm::vec3 viewerPosition = _camera->getPosition(); //_viewerAvatar->getPosition(); +- +- // debug LOD code +- glm::vec3 debugNodePosition; +- copyFirstVertexForCode(currentNode->octalCode,(float*)&debugNodePosition); +- +- float distanceToVoxelCenter = sqrtf(powf(viewerPosition.x - nodePosition[0] - halfUnitForVoxel, 2) + +- 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); +- } ++int VoxelSystem::newTreeToArrays(VoxelNode* node) { ++ assert(_viewFrustum); // you must set up _viewFrustum before calling this ++ int voxelsUpdated = 0; ++ 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)); ++ ++ node->setShouldRender(shouldRender); ++ // let children figure out their renderness ++ for (int i = 0; i < 8; i++) { ++ if (node->children[i]) { ++ voxelsUpdated += newTreeToArrays(node->children[i]); + } + } ++ ++ // 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 +- // add our vertex and color information to the interleaved array +- if (voxelsAdded == 0 && currentNode->isColored()) { +- float startVertex[3]; +- copyFirstVertexForCode(currentNode->octalCode,(float*)&startVertex); +- float voxelScale = 1 / powf(2, *currentNode->octalCode); ++ // If this node has not yet been written to the array, then add it to the end of the array. ++ glBufferIndex nodeIndex; ++ if (node->isKnownBufferIndex()) { ++ nodeIndex = node->getBufferIndex(); ++ } else { ++ nodeIndex = _voxelsInArrays; ++ } ++ ++ _voxelDirtyArray[nodeIndex] = true; + + // 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++ ) { +- *writeVerticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); +- *(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->getColor()[j % 3]; +- +- writeVerticesEndPointer++; ++ GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); ++ GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); ++ *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); ++ *(writeColorsAt +j) = node->getColor()[j % 3]; ++ } ++ if (!node->isKnownBufferIndex()) { ++ node->setBufferIndex(nodeIndex); ++ _voxelsInArrays++; // our know vertices in the arrays + } +- voxelsAdded++; ++ voxelsUpdated++; ++ node->clearDirtyBit(); + } +- +- return voxelsAdded; ++ return voxelsUpdated; + } + + VoxelSystem* VoxelSystem::clone() const { +@@ -230,20 +224,30 @@ VoxelSystem* VoxelSystem::clone() const { + } + + void VoxelSystem::init() { ++ ++ // 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 +- 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]; ++ _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]; ++ GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; + + // populate the indicesArray + // 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++) { + // fill the indices array + int voxelIndexOffset = n * INDICES_PER_VOXEL; +- GLuint *currentIndicesPos = indicesArray + voxelIndexOffset; ++ GLuint* currentIndicesPos = indicesArray + voxelIndexOffset; + int startIndex = (n * VERTICES_PER_VOXEL); + + 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 *normalsArrayEndPointer = normalsArray; ++ GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; ++ GLfloat* normalsArrayEndPointer = normalsArray; + + // populate the normalsArray + for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) { +@@ -263,25 +267,25 @@ void VoxelSystem::init() { + } + + // VBO for the verticesArray +- glGenBuffers(1, &vboVerticesID); +- glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); ++ glGenBuffers(1, &_vboVerticesID); ++ glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); + + // VBO for the normalsArray +- glGenBuffers(1, &vboNormalsID); +- glBindBuffer(GL_ARRAY_BUFFER, vboNormalsID); ++ glGenBuffers(1, &_vboNormalsID); ++ glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); + glBufferData(GL_ARRAY_BUFFER, + VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, + normalsArray, GL_STATIC_DRAW); + + // VBO for colorsArray +- glGenBuffers(1, &vboColorsID); +- glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); ++ glGenBuffers(1, &_vboColorsID); ++ glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); + 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); +- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); ++ glGenBuffers(1, &_vboIndicesID); ++ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, + INDICES_PER_VOXEL * sizeof(GLuint) * MAX_VOXELS_PER_SYSTEM, + indicesArray, GL_STATIC_DRAW); +@@ -291,45 +295,68 @@ void VoxelSystem::init() { + delete[] normalsArray; + } + +-void VoxelSystem::render() { +- +- glPushMatrix(); +- +- if (readVerticesEndPointer != readVerticesArray) { +- // try to lock on the buffer write +- // just avoid pulling new data if it is currently being written +- if (pthread_mutex_trylock(&bufferWriteLock) == 0) { +- +- glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); +- glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLfloat), readVerticesArray); +- +- glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); +- glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLubyte), readColorsArray); +- +- readVerticesEndPointer = readVerticesArray; +- +- pthread_mutex_unlock(&bufferWriteLock); ++void VoxelSystem::updateVBOs() { ++ if (_voxelsDirty) { ++ glBufferIndex segmentStart = 0; ++ glBufferIndex segmentEnd = 0; ++ ++ bool inSegment = false; ++ for (glBufferIndex i = 0; i < _voxelsInArrays; i++) { ++ if (!inSegment) { ++ if (_voxelDirtyArray[i]) { ++ segmentStart = i; ++ inSegment = true; ++ _voxelDirtyArray[i] = false; // consider us clean! ++ } ++ } else { ++ if (!_voxelDirtyArray[i] || (i == (_voxelsInArrays - 1)) ) { ++ segmentEnd = i; ++ inSegment = false; ++ int segmentLength = (segmentEnd - segmentStart) + 1; ++ ++ // vertices for segment - note: we might not need to do this ++ 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); ++ ++ // colors for segment ++ 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 + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + +- glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); ++ glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); + glVertexPointer(3, GL_FLOAT, 0, 0); + +- glBindBuffer(GL_ARRAY_BUFFER, vboNormalsID); ++ glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); + glNormalPointer(GL_FLOAT, 0, 0); + +- glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); ++ glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); + glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); + + // 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 * _voxelsInArrays, GL_UNSIGNED_INT, 0); + + // deactivate vertex and color arrays after drawing + glDisableClientState(GL_VERTEX_ARRAY); +@@ -350,12 +377,7 @@ void VoxelSystem::simulate(float deltaTime) { + + int VoxelSystem::_nodeCount = 0; + +-bool VoxelSystem::randomColorOperation(VoxelNode* node, bool down, void* extraData) { +- +- // we do our operations on the way up! +- if (down) { +- return true; +- } ++bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) { + + _nodeCount++; + if (node->isColored()) { +@@ -370,17 +392,12 @@ bool VoxelSystem::randomColorOperation(VoxelNode* node, bool down, void* extraDa + + void VoxelSystem::randomizeVoxelColors() { + _nodeCount = 0; +- tree->recurseTreeWithOperation(randomColorOperation); ++ _tree->recurseTreeWithOperation(randomColorOperation); + printLog("setting randomized true color for %d nodes\n",_nodeCount); + setupNewVoxelsForDrawing(); + } + +-bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, bool down, void* extraData) { +- +- // we do our operations on the way up! +- if (down) { +- return true; +- } ++bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, void* extraData) { + + _nodeCount++; + +@@ -395,18 +412,12 @@ bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, bool down, void* + + void VoxelSystem::falseColorizeRandom() { + _nodeCount = 0; +- tree->recurseTreeWithOperation(falseColorizeRandomOperation); ++ _tree->recurseTreeWithOperation(falseColorizeRandomOperation); + printLog("setting randomized false color for %d nodes\n",_nodeCount); + setupNewVoxelsForDrawing(); + } + +-bool VoxelSystem::trueColorizeOperation(VoxelNode* node, bool down, void* extraData) { +- +- // we do our operations on the way up! +- if (down) { +- return true; +- } +- ++bool VoxelSystem::trueColorizeOperation(VoxelNode* node, void* extraData) { + _nodeCount++; + node->setFalseColored(false); + return true; +@@ -414,19 +425,13 @@ bool VoxelSystem::trueColorizeOperation(VoxelNode* node, bool down, void* extraD + + void VoxelSystem::trueColorize() { + _nodeCount = 0; +- tree->recurseTreeWithOperation(trueColorizeOperation); ++ _tree->recurseTreeWithOperation(trueColorizeOperation); + printLog("setting true color for %d nodes\n",_nodeCount); + setupNewVoxelsForDrawing(); + } + + // Will false colorize voxels that are not in view +-bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void* extraData) { +- +- // we do our operations on the way up! +- if (down) { +- return true; +- } +- ++bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, void* extraData) { + const ViewFrustum* viewFrustum = (const ViewFrustum*) extraData; + + _nodeCount++; +@@ -448,25 +453,17 @@ bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void* + + void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) { + _nodeCount = 0; +- tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum); ++ _tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum); + printLog("setting in view false color for %d nodes\n",_nodeCount); + setupNewVoxelsForDrawing(); + } + + // Will false colorize voxels based on distance from view +-bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool down, void* extraData) { +- +- // we do our operations on the way up! +- if (down) { +- return true; +- } +- ++bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, void* extraData) { + ViewFrustum* viewFrustum = (ViewFrustum*) extraData; + + // only do this for truly colored voxels... + if (node->isColored()) { +- +- // We need our distance for both up and down + glm::vec3 nodePosition; + float* startVertex = firstVertexForCode(node->octalCode); + nodePosition.x = startVertex[0]; +@@ -508,13 +505,7 @@ float VoxelSystem::_minDistance = FLT_MAX; + // 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 + // we wouldn't need to do two passes of the tree +-bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, bool down, void* extraData) { +- +- // we do our operations on the way up! +- if (down) { +- return true; +- } +- ++bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, void* extraData) { + ViewFrustum* viewFrustum = (ViewFrustum*) extraData; + + // only do this for truly colored voxels... +@@ -538,7 +529,7 @@ bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, bool down, + powf(viewerPosition.y - nodePosition.y - halfUnitForVoxel, 2) + + powf(viewerPosition.z - nodePosition.z - halfUnitForVoxel, 2)); + +- // on way down, calculate the range of distances ++ // calculate the range of distances + if (distance > _maxDistance) { + _maxDistance = distance; + } +@@ -556,12 +547,14 @@ void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) { + + _maxDistance = 0.0; + _minDistance = FLT_MAX; +- tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum); ++ _tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum); + printLog("determining distance range for %d nodes\n",_nodeCount); + + _nodeCount = 0; + +- tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum); ++ _tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum); + printLog("setting in distance false color for %d nodes\n",_nodeCount); + setupNewVoxelsForDrawing(); + } ++ ++ +diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h +index f12cc75..04f9f8c 100644 +--- a/interface/src/VoxelSystem.h ++++ b/interface/src/VoxelSystem.h +@@ -29,12 +29,16 @@ public: + + int parseData(unsigned char* sourceBuffer, int numBytes); + VoxelSystem* clone() const; ++ ++ void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }; + + void init(); + void simulate(float deltaTime); + 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 setCamera(Camera* newCamera) { _camera = newCamera; }; + void loadVoxelsFile(const char* fileName,bool wantColorRandomizer); +@@ -57,36 +61,42 @@ public: + private: + // Operation functions for tree recursion methods + static int _nodeCount; +- static bool randomColorOperation(VoxelNode* node, bool down, void* extraData); +- static bool falseColorizeRandomOperation(VoxelNode* node, bool down, void* extraData); +- static bool trueColorizeOperation(VoxelNode* node, bool down, void* extraData); +- static bool falseColorizeInViewOperation(VoxelNode* node, bool down, void* extraData); +- static bool falseColorizeDistanceFromViewOperation(VoxelNode* node, bool down, void* extraData); +- static bool getDistanceFromViewRangeOperation(VoxelNode* node, bool down, void* extraData); ++ static bool randomColorOperation(VoxelNode* node, void* extraData); ++ static bool falseColorizeRandomOperation(VoxelNode* node, void* extraData); ++ static bool trueColorizeOperation(VoxelNode* node, void* extraData); ++ static bool falseColorizeInViewOperation(VoxelNode* node, void* extraData); ++ static bool falseColorizeDistanceFromViewOperation(VoxelNode* node, void* extraData); ++ static bool getDistanceFromViewRangeOperation(VoxelNode* node, void* extraData); + + // these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here + static float _maxDistance; + static float _minDistance; + +- int voxelsRendered; + Avatar* _viewerAvatar; + Camera* _camera; +- VoxelTree *tree; +- GLfloat *readVerticesArray; +- GLubyte *readColorsArray; +- GLfloat *readVerticesEndPointer; +- GLfloat *writeVerticesArray; +- GLubyte *writeColorsArray; +- GLfloat *writeVerticesEndPointer; +- GLuint vboVerticesID; +- GLuint vboNormalsID; +- GLuint vboColorsID; +- GLuint vboIndicesID; +- pthread_mutex_t bufferWriteLock; +- +- int treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosition); ++ VoxelTree* _tree; ++ GLfloat* _readVerticesArray; ++ GLubyte* _readColorsArray; ++ GLfloat* _writeVerticesArray; ++ GLubyte* _writeColorsArray; ++ bool* _voxelDirtyArray; ++ unsigned long _voxelsUpdated; ++ unsigned long _voxelsInArrays; ++ ++ GLuint _vboVerticesID; ++ GLuint _vboNormalsID; ++ GLuint _vboColorsID; ++ GLuint _vboIndicesID; ++ pthread_mutex_t _bufferWriteLock; ++ ++ ViewFrustum* _viewFrustum; ++ ++ int newTreeToArrays(VoxelNode *currentNode); + void setupNewVoxelsForDrawing(); + void copyWrittenDataToReadArrays(); ++ void updateVBOs(); ++ ++ bool _voxelsDirty; + }; + + #endif +diff --git a/interface/src/main.cpp b/interface/src/main.cpp +index 7ef1c49..b73d58f 100644 +--- a/interface/src/main.cpp ++++ b/interface/src/main.cpp +@@ -230,7 +230,7 @@ void displayStats(void) + drawtext(10, statsVerticalOffset + 49, 0.10f, 0, 1.0, 0, stats); + + 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()); + + voxelStats.str(""); +@@ -1612,6 +1612,8 @@ void audioMixerUpdate(in_addr_t newMixerAddress, in_port_t newMixerPort) { + + int main(int argc, const char * argv[]) + { ++ voxels.setViewFrustum(&::viewFrustum); ++ + shared_lib::printLog = & ::printLog; + voxels_lib::printLog = & ::printLog; + avatars_lib::printLog = & ::printLog; +@@ -1634,7 +1636,7 @@ int main(int argc, const char * argv[]) + } + + // 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"); + int ip = getLocalAddress(); + sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF)); +diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h +index 66ddbcb..2ba4d05 100644 +--- a/libraries/voxels/src/VoxelConstants.h ++++ b/libraries/voxels/src/VoxelConstants.h +@@ -21,4 +21,7 @@ const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; + const int INDICES_PER_VOXEL = 3 * 12; + const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; + ++typedef unsigned long int glBufferIndex; ++const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX; ++ + #endif +diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp +index c1527d3..6f8f1d7 100644 +--- a/libraries/voxels/src/VoxelNode.cpp ++++ b/libraries/voxels/src/VoxelNode.cpp +@@ -30,6 +30,10 @@ VoxelNode::VoxelNode() { + for (int i = 0; i < 8; i++) { + children[i] = NULL; + } ++ ++ _glBufferIndex = GLBUFFER_INDEX_UNKNOWN; ++ _isDirty = true; ++ _shouldRender = false; + } + + 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 { + + glm::vec3 corner; +@@ -59,16 +71,19 @@ void VoxelNode::getAABox(AABox& box) const { + } + + 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 +- // 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 +- // it to not-false-colored here! +- children[childIndex]->setFalseColored(false); ++ // 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 ++ // to-do to research this. But for now we'll use belt and suspenders and set ++ // it to not-false-colored here! ++ children[childIndex]->setFalseColored(false); + +- // give this child its octal code +- children[childIndex]->octalCode = childOctalCode(octalCode, childIndex); ++ // give this child its octal code ++ children[childIndex]->octalCode = childOctalCode(octalCode, childIndex); ++ _isDirty = true; ++ } + } + + // will average the child colors... +@@ -104,26 +119,35 @@ void VoxelNode::setColorFromAverageOfChildren() { + // the actual NO_FALSE_COLOR version are inline in the VoxelNode.h + #ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color + void VoxelNode::setFalseColor(colorPart red, colorPart green, colorPart blue) { +- _falseColored=true; +- _currentColor[0] = red; +- _currentColor[1] = green; +- _currentColor[2] = blue; +- _currentColor[3] = 1; // XXXBHG - False colors are always considered set ++ if (_falseColored != true || _currentColor[0] != red || _currentColor[1] != green || _currentColor[2] != blue) { ++ _falseColored=true; ++ _currentColor[0] = red; ++ _currentColor[1] = green; ++ _currentColor[2] = blue; ++ _currentColor[3] = 1; // XXXBHG - False colors are always considered set ++ _isDirty = true; ++ } + } + + void VoxelNode::setFalseColored(bool isFalseColored) { +- // if we were false colored, and are no longer false colored, then swap back +- if (_falseColored && !isFalseColored) { +- memcpy(&_currentColor,&_trueColor,sizeof(nodeColor)); ++ if (_falseColored != isFalseColored) { ++ // if we were false colored, and are no longer false colored, then swap back ++ if (_falseColored && !isFalseColored) { ++ memcpy(&_currentColor,&_trueColor,sizeof(nodeColor)); ++ } ++ _falseColored = isFalseColored; ++ _isDirty = true; + } +- _falseColored = isFalseColored; + }; + + + void VoxelNode::setColor(const nodeColor& color) { +- memcpy(&_trueColor,&color,sizeof(nodeColor)); +- if (!_falseColored) { +- memcpy(&_currentColor,&color,sizeof(nodeColor)); ++ if (_trueColor[0] != color[0] || _trueColor[1] != color[1] || _trueColor[2] != color[2]) { ++ memcpy(&_trueColor,&color,sizeof(nodeColor)); ++ if (!_falseColored) { ++ memcpy(&_currentColor,&color,sizeof(nodeColor)); ++ } ++ _isDirty = true; + } + } + #endif +@@ -199,7 +223,6 @@ void VoxelNode::printDebugDetails(const char* label) const { + printOctalCode(octalCode); + } + +- + bool VoxelNode::isInView(const ViewFrustum& viewFrustum) const { + AABox box; + getAABox(box); +diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h +index 4cda55f..cbd9b8a 100644 +--- a/libraries/voxels/src/VoxelNode.h ++++ b/libraries/voxels/src/VoxelNode.h +@@ -11,6 +11,7 @@ + + #include "AABox.h" + #include "ViewFrustum.h" ++#include "VoxelConstants.h" + + typedef unsigned char colorPart; + typedef unsigned char nodeColor[4]; +@@ -22,6 +23,11 @@ private: + nodeColor _currentColor; + bool _falseColored; + #endif ++ ++ glBufferIndex _glBufferIndex; ++ bool _isDirty; ++ bool _shouldRender; ++ + public: + VoxelNode(); + ~VoxelNode(); +@@ -40,6 +46,18 @@ public: + bool isLeaf() const; + void getAABox(AABox& box) 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; }; ++ ++ // whether or not we should render ++ void setShouldRender(bool shouldRender); ++ bool getShouldRender() const { return _shouldRender; } ++ + + #ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color + void setFalseColor(colorPart red, colorPart green, colorPart blue); +diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp +index cbbcced..3ff14b5 100644 +--- a/libraries/voxels/src/VoxelTree.cpp ++++ b/libraries/voxels/src/VoxelTree.cpp +@@ -58,16 +58,13 @@ void VoxelTree::recurseTreeWithOperation(RecurseVoxelTreeOperation operation, vo + + // Recurses voxel node with an operation function + 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,true,extraData)) { +- for (int i = 0; i < sizeof(node->children)/sizeof(node->children[0]); i++) { ++ if (operation(node, extraData)) { ++ for (int i = 0; i < sizeof(node->children) / sizeof(node->children[0]); i++) { + VoxelNode* child = node->children[i]; + if (child) { +- recurseNodeWithOperation(child,operation,extraData); ++ recurseNodeWithOperation(child, operation, extraData); + } + } +- // call operation on way back up +- operation(node,false,extraData); + } + } + +diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h +index ac3c762..7f5a6b8 100644 +--- a/libraries/voxels/src/VoxelTree.h ++++ b/libraries/voxels/src/VoxelTree.h +@@ -16,7 +16,7 @@ + #include "VoxelNodeBag.h" + + // Callback function, for recuseTreeWithOperation +-typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, bool down, void* extraData); ++typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, void* extraData); + + class VoxelTree { + public: +diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp +index 716a4e9..9ab5675 100644 +--- a/voxel-server/src/main.cpp ++++ b/voxel-server/src/main.cpp +@@ -38,7 +38,7 @@ const float DEATH_STAR_RADIUS = 4.0; + const float MAX_CUBE = 0.05f; + + 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; + +@@ -68,11 +68,9 @@ void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) { + } + + int _nodeCount=0; +-bool countVoxelsOperation(VoxelNode* node, bool down, void* extraData) { +- if (down) { +- if (node->isColored()){ +- _nodeCount++; +- } ++bool countVoxelsOperation(VoxelNode* node, void* extraData) { ++ if (node->isColored()){ ++ _nodeCount++; + } + return true; // keep going + } +@@ -80,7 +78,7 @@ bool countVoxelsOperation(VoxelNode* node, bool down, void* extraData) { + void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) { + 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); + printf("one sphere added...\n"); diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 24f7665e50..b8157d0943 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -41,69 +41,53 @@ GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- . 4,5,6, 4,6,7 }; // Z+ . VoxelSystem::VoxelSystem() { - voxelsRendered = 0; - tree = new VoxelTree(); - pthread_mutex_init(&bufferWriteLock, NULL); + _voxelsInArrays = _voxelsUpdated = 0; + _tree = new VoxelTree(); + pthread_mutex_init(&_bufferWriteLock, NULL); } VoxelSystem::~VoxelSystem() { - delete[] readVerticesArray; - delete[] writeVerticesArray; - delete[] readColorsArray; - delete[] writeColorsArray; - delete tree; - pthread_mutex_destroy(&bufferWriteLock); + delete[] _readVerticesArray; + delete[] _writeVerticesArray; + delete[] _readColorsArray; + delete[] _writeColorsArray; + delete[] _voxelDirtyArray; + 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) { - - tree->loadVoxelsFile(fileName,wantColorRandomizer); - + _tree->loadVoxelsFile(fileName, wantColorRandomizer); 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) { - - tree->createSphere(r,xc,yc,zc,s,solid,wantColorRandomizer); + _tree->createSphere(r, xc, yc, zc, s, solid, wantColorRandomizer); setupNewVoxelsForDrawing(); } long int VoxelSystem::getVoxelsCreated() { - return tree->voxelsCreated; + return _tree->voxelsCreated; } float VoxelSystem::getVoxelsCreatedPerSecondAverage() { - return (1 / tree->voxelsCreatedStats.getEventDeltaAverage()); + return (1 / _tree->voxelsCreatedStats.getEventDeltaAverage()); } long int VoxelSystem::getVoxelsColored() { - return tree->voxelsColored; + return _tree->voxelsColored; } float VoxelSystem::getVoxelsColoredPerSecondAverage() { - return (1 / tree->voxelsColoredStats.getEventDeltaAverage()); + return (1 / _tree->voxelsColoredStats.getEventDeltaAverage()); } long int VoxelSystem::getVoxelsBytesRead() { - return tree->voxelsBytesRead; + return _tree->voxelsBytesRead; } float VoxelSystem::getVoxelsBytesReadPerSecondAverage() { - return tree->voxelsBytesReadStats.getAverageSampleValuePerSecond(); + return _tree->voxelsBytesReadStats.getAverageSampleValuePerSecond(); } int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { @@ -114,11 +98,11 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { switch(command) { case PACKET_HEADER_VOXEL_DATA: // ask the VoxelTree to read the bitstream into the tree - tree->readBitstreamToTree(voxelData, numBytes - 1); + _tree->readBitstreamToTree(voxelData, numBytes - 1); break; case PACKET_HEADER_ERASE_VOXEL: // ask the tree to read the "remove" bitstream - tree->processRemoveVoxelBitstream(sourceBuffer, numBytes); + _tree->processRemoveVoxelBitstream(sourceBuffer, numBytes); break; case PACKET_HEADER_Z_COMMAND: @@ -135,7 +119,8 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { while (totalLength <= numBytes) { if (0==strcmp(command,(char*)"erase all")) { 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")) { 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() { - // reset the verticesEndPointer so we're writing to the beginning of the array - writeVerticesEndPointer = writeVerticesArray; - // call recursive function to populate in memory arrays - // it will return the number of voxels added - glm::vec3 treeRoot = glm::vec3(0,0,0); - voxelsRendered = treeToArrays(tree->rootNode, treeRoot); + _voxelsUpdated = newTreeToArrays(_tree->rootNode); + if (_voxelsUpdated) { + _voxelsDirty=true; + } + // copy the newly written data to the arrays designated for reading copyWrittenDataToReadArrays(); } void VoxelSystem::copyWrittenDataToReadArrays() { - // lock on the buffer write lock so we can't modify the data when the GPU is reading it - pthread_mutex_lock(&bufferWriteLock); - // store a pointer to the current end so it doesn't change during copy - GLfloat *endOfCurrentVerticesData = writeVerticesEndPointer; - // copy the vertices and colors - memcpy(readVerticesArray, writeVerticesArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLfloat)); - memcpy(readColorsArray, writeColorsArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLubyte)); - // set the read vertices end pointer to the correct spot so the GPU knows how much to pull - readVerticesEndPointer = readVerticesArray + (endOfCurrentVerticesData - writeVerticesArray); - pthread_mutex_unlock(&bufferWriteLock); + if (_voxelsDirty) { + // lock on the buffer write lock so we can't modify the data when the GPU is reading it + pthread_mutex_lock(&_bufferWriteLock); + int bytesOfVertices = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat); + int bytesOfColors = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLubyte); + memcpy(_readVerticesArray, _writeVerticesArray, bytesOfVertices); + memcpy(_readColorsArray, _writeColorsArray, bytesOfColors ); + pthread_mutex_unlock(&_bufferWriteLock); + } } -int VoxelSystem::treeToArrays(VoxelNode* currentNode, const glm::vec3& nodePosition) { - int voxelsAdded = 0; - float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE); - glm::vec3 viewerPosition = _camera->getPosition(); //_viewerAvatar->getPosition(); +int VoxelSystem::newTreeToArrays(VoxelNode* node) { + assert(_viewFrustum); // you must set up _viewFrustum before calling this + int voxelsUpdated = 0; + 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 - glm::vec3 debugNodePosition; - copyFirstVertexForCode(currentNode->octalCode,(float*)&debugNodePosition); - - float distanceToVoxelCenter = sqrtf(powf(viewerPosition.x - nodePosition[0] - halfUnitForVoxel, 2) + - 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); - } + node->setShouldRender(shouldRender); + // let children figure out their renderness + for (int i = 0; i < 8; i++) { + if (node->children[i]) { + voxelsUpdated += newTreeToArrays(node->children[i]); } } + + // 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 - // add our vertex and color information to the interleaved array - if (voxelsAdded == 0 && currentNode->isColored()) { - float startVertex[3]; - copyFirstVertexForCode(currentNode->octalCode,(float*)&startVertex); - float voxelScale = 1 / powf(2, *currentNode->octalCode); + // If this node has not yet been written to the array, then add it to the end of the array. + glBufferIndex nodeIndex; + if (node->isKnownBufferIndex()) { + nodeIndex = node->getBufferIndex(); + } else { + nodeIndex = _voxelsInArrays; + } + + _voxelDirtyArray[nodeIndex] = true; // 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++ ) { - *writeVerticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); - *(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->getColor()[j % 3]; - - writeVerticesEndPointer++; + GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); + GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); + *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); + *(writeColorsAt +j) = node->getColor()[j % 3]; } - voxelsAdded++; + if (!node->isKnownBufferIndex()) { + node->setBufferIndex(nodeIndex); + _voxelsInArrays++; // our know vertices in the arrays + } + voxelsUpdated++; + node->clearDirtyBit(); } - - return voxelsAdded; + return voxelsUpdated; } VoxelSystem* VoxelSystem::clone() const { @@ -230,20 +224,30 @@ VoxelSystem* VoxelSystem::clone() const { } 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 // 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++) { // fill the indices array int voxelIndexOffset = n * INDICES_PER_VOXEL; - GLuint *currentIndicesPos = indicesArray + voxelIndexOffset; + GLuint* currentIndicesPos = indicesArray + voxelIndexOffset; int startIndex = (n * VERTICES_PER_VOXEL); 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 *normalsArrayEndPointer = normalsArray; + GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; + GLfloat* normalsArrayEndPointer = normalsArray; // populate the normalsArray for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) { @@ -263,25 +267,25 @@ void VoxelSystem::init() { } // VBO for the verticesArray - glGenBuffers(1, &vboVerticesID); - glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); + glGenBuffers(1, &_vboVerticesID); + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); // VBO for the normalsArray - glGenBuffers(1, &vboNormalsID); - glBindBuffer(GL_ARRAY_BUFFER, vboNormalsID); + glGenBuffers(1, &_vboNormalsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, normalsArray, GL_STATIC_DRAW); // VBO for colorsArray - glGenBuffers(1, &vboColorsID); - glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); + glGenBuffers(1, &_vboColorsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); 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); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); + glGenBuffers(1, &_vboIndicesID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, INDICES_PER_VOXEL * sizeof(GLuint) * MAX_VOXELS_PER_SYSTEM, indicesArray, GL_STATIC_DRAW); @@ -291,45 +295,68 @@ void VoxelSystem::init() { delete[] normalsArray; } -void VoxelSystem::render() { +void VoxelSystem::updateVBOs() { + if (_voxelsDirty) { + glBufferIndex segmentStart = 0; + glBufferIndex segmentEnd = 0; + + bool inSegment = false; + for (glBufferIndex i = 0; i < _voxelsInArrays; i++) { + if (!inSegment) { + if (_voxelDirtyArray[i]) { + segmentStart = i; + inSegment = true; + _voxelDirtyArray[i] = false; // consider us clean! + } + } else { + if (!_voxelDirtyArray[i] || (i == (_voxelsInArrays - 1)) ) { + segmentEnd = i; + inSegment = false; + int segmentLength = (segmentEnd - segmentStart) + 1; - glPushMatrix(); + // vertices for segment - note: we might not need to do this + 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); - if (readVerticesEndPointer != readVerticesArray) { - // try to lock on the buffer write - // just avoid pulling new data if it is currently being written - if (pthread_mutex_trylock(&bufferWriteLock) == 0) { + // colors for segment + 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, vboVerticesID); - glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLfloat), readVerticesArray); - - glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); - glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLubyte), readColorsArray); - - readVerticesEndPointer = readVerticesArray; - - pthread_mutex_unlock(&bufferWriteLock); + 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 glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); - glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); glVertexPointer(3, GL_FLOAT, 0, 0); - glBindBuffer(GL_ARRAY_BUFFER, vboNormalsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); glNormalPointer(GL_FLOAT, 0, 0); - glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); // 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 * _voxelsInArrays, GL_UNSIGNED_INT, 0); // deactivate vertex and color arrays after drawing glDisableClientState(GL_VERTEX_ARRAY); @@ -350,12 +377,7 @@ void VoxelSystem::simulate(float deltaTime) { int VoxelSystem::_nodeCount = 0; -bool VoxelSystem::randomColorOperation(VoxelNode* node, bool down, void* extraData) { - - // we do our operations on the way up! - if (down) { - return true; - } +bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) { _nodeCount++; if (node->isColored()) { @@ -370,17 +392,12 @@ bool VoxelSystem::randomColorOperation(VoxelNode* node, bool down, void* extraDa void VoxelSystem::randomizeVoxelColors() { _nodeCount = 0; - tree->recurseTreeWithOperation(randomColorOperation); + _tree->recurseTreeWithOperation(randomColorOperation); printLog("setting randomized true color for %d nodes\n",_nodeCount); setupNewVoxelsForDrawing(); } -bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, bool down, void* extraData) { - - // we do our operations on the way up! - if (down) { - return true; - } +bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, void* extraData) { _nodeCount++; @@ -395,18 +412,12 @@ bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, bool down, void* void VoxelSystem::falseColorizeRandom() { _nodeCount = 0; - tree->recurseTreeWithOperation(falseColorizeRandomOperation); + _tree->recurseTreeWithOperation(falseColorizeRandomOperation); printLog("setting randomized false color for %d nodes\n",_nodeCount); setupNewVoxelsForDrawing(); } -bool VoxelSystem::trueColorizeOperation(VoxelNode* node, bool down, void* extraData) { - - // we do our operations on the way up! - if (down) { - return true; - } - +bool VoxelSystem::trueColorizeOperation(VoxelNode* node, void* extraData) { _nodeCount++; node->setFalseColored(false); return true; @@ -414,19 +425,13 @@ bool VoxelSystem::trueColorizeOperation(VoxelNode* node, bool down, void* extraD void VoxelSystem::trueColorize() { _nodeCount = 0; - tree->recurseTreeWithOperation(trueColorizeOperation); + _tree->recurseTreeWithOperation(trueColorizeOperation); printLog("setting true color for %d nodes\n",_nodeCount); setupNewVoxelsForDrawing(); } // Will false colorize voxels that are not in view -bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void* extraData) { - - // we do our operations on the way up! - if (down) { - return true; - } - +bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, void* extraData) { const ViewFrustum* viewFrustum = (const ViewFrustum*) extraData; _nodeCount++; @@ -448,25 +453,17 @@ bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void* void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) { _nodeCount = 0; - tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum); + _tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum); printLog("setting in view false color for %d nodes\n",_nodeCount); setupNewVoxelsForDrawing(); } // Will false colorize voxels based on distance from view -bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool down, void* extraData) { - - // we do our operations on the way up! - if (down) { - return true; - } - +bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, void* extraData) { ViewFrustum* viewFrustum = (ViewFrustum*) extraData; // only do this for truly colored voxels... if (node->isColored()) { - - // We need our distance for both up and down glm::vec3 nodePosition; float* startVertex = firstVertexForCode(node->octalCode); nodePosition.x = startVertex[0]; @@ -508,13 +505,7 @@ float VoxelSystem::_minDistance = FLT_MAX; // 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 // we wouldn't need to do two passes of the tree -bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, bool down, void* extraData) { - - // we do our operations on the way up! - if (down) { - return true; - } - +bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, void* extraData) { ViewFrustum* viewFrustum = (ViewFrustum*) extraData; // only do this for truly colored voxels... @@ -538,7 +529,7 @@ bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, bool down, powf(viewerPosition.y - nodePosition.y - halfUnitForVoxel, 2) + powf(viewerPosition.z - nodePosition.z - halfUnitForVoxel, 2)); - // on way down, calculate the range of distances + // calculate the range of distances if (distance > _maxDistance) { _maxDistance = distance; } @@ -556,12 +547,14 @@ void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) { _maxDistance = 0.0; _minDistance = FLT_MAX; - tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum); + _tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum); printLog("determining distance range for %d nodes\n",_nodeCount); _nodeCount = 0; - tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum); + _tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum); printLog("setting in distance false color for %d nodes\n",_nodeCount); setupNewVoxelsForDrawing(); } + + diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index f12cc7521a..04f9f8ceb7 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -29,12 +29,16 @@ public: int parseData(unsigned char* sourceBuffer, int numBytes); VoxelSystem* clone() const; + + void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }; void init(); void simulate(float deltaTime); 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 setCamera(Camera* newCamera) { _camera = newCamera; }; void loadVoxelsFile(const char* fileName,bool wantColorRandomizer); @@ -57,36 +61,42 @@ public: private: // Operation functions for tree recursion methods static int _nodeCount; - static bool randomColorOperation(VoxelNode* node, bool down, void* extraData); - static bool falseColorizeRandomOperation(VoxelNode* node, bool down, void* extraData); - static bool trueColorizeOperation(VoxelNode* node, bool down, void* extraData); - static bool falseColorizeInViewOperation(VoxelNode* node, bool down, void* extraData); - static bool falseColorizeDistanceFromViewOperation(VoxelNode* node, bool down, void* extraData); - static bool getDistanceFromViewRangeOperation(VoxelNode* node, bool down, void* extraData); + static bool randomColorOperation(VoxelNode* node, void* extraData); + static bool falseColorizeRandomOperation(VoxelNode* node, void* extraData); + static bool trueColorizeOperation(VoxelNode* node, void* extraData); + static bool falseColorizeInViewOperation(VoxelNode* node, void* extraData); + static bool falseColorizeDistanceFromViewOperation(VoxelNode* node, void* extraData); + static bool getDistanceFromViewRangeOperation(VoxelNode* node, void* extraData); // these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here static float _maxDistance; static float _minDistance; - int voxelsRendered; Avatar* _viewerAvatar; Camera* _camera; - VoxelTree *tree; - GLfloat *readVerticesArray; - GLubyte *readColorsArray; - GLfloat *readVerticesEndPointer; - GLfloat *writeVerticesArray; - GLubyte *writeColorsArray; - GLfloat *writeVerticesEndPointer; - GLuint vboVerticesID; - GLuint vboNormalsID; - GLuint vboColorsID; - GLuint vboIndicesID; - pthread_mutex_t bufferWriteLock; + VoxelTree* _tree; + GLfloat* _readVerticesArray; + GLubyte* _readColorsArray; + GLfloat* _writeVerticesArray; + GLubyte* _writeColorsArray; + bool* _voxelDirtyArray; + unsigned long _voxelsUpdated; + unsigned long _voxelsInArrays; + + GLuint _vboVerticesID; + GLuint _vboNormalsID; + 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 copyWrittenDataToReadArrays(); + void updateVBOs(); + + bool _voxelsDirty; }; #endif diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 7ef1c491f8..b73d58f88a 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -230,7 +230,7 @@ void displayStats(void) drawtext(10, statsVerticalOffset + 49, 0.10f, 0, 1.0, 0, stats); 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()); voxelStats.str(""); @@ -1612,6 +1612,8 @@ void audioMixerUpdate(in_addr_t newMixerAddress, in_port_t newMixerPort) { int main(int argc, const char * argv[]) { + voxels.setViewFrustum(&::viewFrustum); + shared_lib::printLog = & ::printLog; voxels_lib::printLog = & ::printLog; avatars_lib::printLog = & ::printLog; @@ -1634,7 +1636,7 @@ int main(int argc, const char * argv[]) } // 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"); int ip = getLocalAddress(); sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF)); diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 66ddbcb915..2ba4d05e31 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -21,4 +21,7 @@ const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; const int INDICES_PER_VOXEL = 3 * 12; const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; +typedef unsigned long int glBufferIndex; +const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX; + #endif diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index c1527d3334..6f8f1d71f8 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -30,6 +30,10 @@ VoxelNode::VoxelNode() { for (int i = 0; i < 8; i++) { children[i] = NULL; } + + _glBufferIndex = GLBUFFER_INDEX_UNKNOWN; + _isDirty = true; + _shouldRender = false; } 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 { glm::vec3 corner; @@ -59,16 +71,19 @@ void VoxelNode::getAABox(AABox& box) const { } 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 - // 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 - // it to not-false-colored here! - children[childIndex]->setFalseColored(false); + // 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 + // to-do to research this. But for now we'll use belt and suspenders and set + // it to not-false-colored here! + children[childIndex]->setFalseColored(false); - // give this child its octal code - children[childIndex]->octalCode = childOctalCode(octalCode, childIndex); + // give this child its octal code + children[childIndex]->octalCode = childOctalCode(octalCode, childIndex); + _isDirty = true; + } } // will average the child colors... @@ -104,26 +119,35 @@ void VoxelNode::setColorFromAverageOfChildren() { // the actual NO_FALSE_COLOR version are inline in the VoxelNode.h #ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color void VoxelNode::setFalseColor(colorPart red, colorPart green, colorPart blue) { - _falseColored=true; - _currentColor[0] = red; - _currentColor[1] = green; - _currentColor[2] = blue; - _currentColor[3] = 1; // XXXBHG - False colors are always considered set + if (_falseColored != true || _currentColor[0] != red || _currentColor[1] != green || _currentColor[2] != blue) { + _falseColored=true; + _currentColor[0] = red; + _currentColor[1] = green; + _currentColor[2] = blue; + _currentColor[3] = 1; // XXXBHG - False colors are always considered set + _isDirty = true; + } } void VoxelNode::setFalseColored(bool isFalseColored) { - // if we were false colored, and are no longer false colored, then swap back - if (_falseColored && !isFalseColored) { - memcpy(&_currentColor,&_trueColor,sizeof(nodeColor)); + if (_falseColored != isFalseColored) { + // if we were false colored, and are no longer false colored, then swap back + if (_falseColored && !isFalseColored) { + memcpy(&_currentColor,&_trueColor,sizeof(nodeColor)); + } + _falseColored = isFalseColored; + _isDirty = true; } - _falseColored = isFalseColored; }; void VoxelNode::setColor(const nodeColor& color) { - memcpy(&_trueColor,&color,sizeof(nodeColor)); - if (!_falseColored) { - memcpy(&_currentColor,&color,sizeof(nodeColor)); + if (_trueColor[0] != color[0] || _trueColor[1] != color[1] || _trueColor[2] != color[2]) { + memcpy(&_trueColor,&color,sizeof(nodeColor)); + if (!_falseColored) { + memcpy(&_currentColor,&color,sizeof(nodeColor)); + } + _isDirty = true; } } #endif @@ -199,7 +223,6 @@ void VoxelNode::printDebugDetails(const char* label) const { printOctalCode(octalCode); } - bool VoxelNode::isInView(const ViewFrustum& viewFrustum) const { AABox box; getAABox(box); diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index 4cda55f8a7..cbd9b8af47 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -11,6 +11,7 @@ #include "AABox.h" #include "ViewFrustum.h" +#include "VoxelConstants.h" typedef unsigned char colorPart; typedef unsigned char nodeColor[4]; @@ -22,6 +23,11 @@ private: nodeColor _currentColor; bool _falseColored; #endif + + glBufferIndex _glBufferIndex; + bool _isDirty; + bool _shouldRender; + public: VoxelNode(); ~VoxelNode(); @@ -40,6 +46,18 @@ public: bool isLeaf() const; void getAABox(AABox& box) 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; }; + + // whether or not we should render + void setShouldRender(bool shouldRender); + bool getShouldRender() const { return _shouldRender; } + #ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color void setFalseColor(colorPart red, colorPart green, colorPart blue); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index cbbccedb59..3ff14b5afd 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -58,16 +58,13 @@ void VoxelTree::recurseTreeWithOperation(RecurseVoxelTreeOperation operation, vo // Recurses voxel node with an operation function 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,true,extraData)) { - for (int i = 0; i < sizeof(node->children)/sizeof(node->children[0]); i++) { + if (operation(node, extraData)) { + for (int i = 0; i < sizeof(node->children) / sizeof(node->children[0]); i++) { VoxelNode* child = node->children[i]; if (child) { - recurseNodeWithOperation(child,operation,extraData); + recurseNodeWithOperation(child, operation, extraData); } } - // call operation on way back up - operation(node,false,extraData); } } diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index ac3c762fcf..7f5a6b866b 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -16,7 +16,7 @@ #include "VoxelNodeBag.h" // Callback function, for recuseTreeWithOperation -typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, bool down, void* extraData); +typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, void* extraData); class VoxelTree { public: diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 716a4e9d7b..9ab5675d7e 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -38,7 +38,7 @@ const float DEATH_STAR_RADIUS = 4.0; const float MAX_CUBE = 0.05f; 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; @@ -68,11 +68,9 @@ void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) { } int _nodeCount=0; -bool countVoxelsOperation(VoxelNode* node, bool down, void* extraData) { - if (down) { - if (node->isColored()){ - _nodeCount++; - } +bool countVoxelsOperation(VoxelNode* node, void* extraData) { + if (node->isColored()){ + _nodeCount++; } return true; // keep going } @@ -80,7 +78,7 @@ bool countVoxelsOperation(VoxelNode* node, bool down, void* extraData) { void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) { 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); printf("one sphere added...\n"); From 9e374cbf33d5cd0cb6a5c0455a33ae2aaf5d0180 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 1 May 2013 18:23:39 -0700 Subject: [PATCH 2/6] removed accidentally added file --- diff.out | 941 ------------------------------------------------------- 1 file changed, 941 deletions(-) delete mode 100644 diff.out diff --git a/diff.out b/diff.out deleted file mode 100644 index 5acd0ea285..0000000000 --- a/diff.out +++ /dev/null @@ -1,941 +0,0 @@ -diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp -index 24f7665..b8157d0 100644 ---- a/interface/src/VoxelSystem.cpp -+++ b/interface/src/VoxelSystem.cpp -@@ -41,69 +41,53 @@ GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- . - 4,5,6, 4,6,7 }; // Z+ . - - VoxelSystem::VoxelSystem() { -- voxelsRendered = 0; -- tree = new VoxelTree(); -- pthread_mutex_init(&bufferWriteLock, NULL); -+ _voxelsInArrays = _voxelsUpdated = 0; -+ _tree = new VoxelTree(); -+ pthread_mutex_init(&_bufferWriteLock, NULL); - } - - VoxelSystem::~VoxelSystem() { -- delete[] readVerticesArray; -- delete[] writeVerticesArray; -- delete[] readColorsArray; -- delete[] writeColorsArray; -- delete tree; -- pthread_mutex_destroy(&bufferWriteLock); -+ delete[] _readVerticesArray; -+ delete[] _writeVerticesArray; -+ delete[] _readColorsArray; -+ delete[] _writeColorsArray; -+ delete[] _voxelDirtyArray; -+ 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) { -- -- tree->loadVoxelsFile(fileName,wantColorRandomizer); -- -+ _tree->loadVoxelsFile(fileName, wantColorRandomizer); - 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) { -- -- tree->createSphere(r,xc,yc,zc,s,solid,wantColorRandomizer); -+ _tree->createSphere(r, xc, yc, zc, s, solid, wantColorRandomizer); - setupNewVoxelsForDrawing(); - } - - long int VoxelSystem::getVoxelsCreated() { -- return tree->voxelsCreated; -+ return _tree->voxelsCreated; - } - - float VoxelSystem::getVoxelsCreatedPerSecondAverage() { -- return (1 / tree->voxelsCreatedStats.getEventDeltaAverage()); -+ return (1 / _tree->voxelsCreatedStats.getEventDeltaAverage()); - } - - long int VoxelSystem::getVoxelsColored() { -- return tree->voxelsColored; -+ return _tree->voxelsColored; - } - - float VoxelSystem::getVoxelsColoredPerSecondAverage() { -- return (1 / tree->voxelsColoredStats.getEventDeltaAverage()); -+ return (1 / _tree->voxelsColoredStats.getEventDeltaAverage()); - } - - long int VoxelSystem::getVoxelsBytesRead() { -- return tree->voxelsBytesRead; -+ return _tree->voxelsBytesRead; - } - - float VoxelSystem::getVoxelsBytesReadPerSecondAverage() { -- return tree->voxelsBytesReadStats.getAverageSampleValuePerSecond(); -+ return _tree->voxelsBytesReadStats.getAverageSampleValuePerSecond(); - } - - int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { -@@ -114,11 +98,11 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { - switch(command) { - case PACKET_HEADER_VOXEL_DATA: - // ask the VoxelTree to read the bitstream into the tree -- tree->readBitstreamToTree(voxelData, numBytes - 1); -+ _tree->readBitstreamToTree(voxelData, numBytes - 1); - break; - case PACKET_HEADER_ERASE_VOXEL: - // ask the tree to read the "remove" bitstream -- tree->processRemoveVoxelBitstream(sourceBuffer, numBytes); -+ _tree->processRemoveVoxelBitstream(sourceBuffer, numBytes); - break; - case PACKET_HEADER_Z_COMMAND: - -@@ -135,7 +119,8 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { - while (totalLength <= numBytes) { - if (0==strcmp(command,(char*)"erase all")) { - 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")) { - 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() { -- // reset the verticesEndPointer so we're writing to the beginning of the array -- writeVerticesEndPointer = writeVerticesArray; -- // call recursive function to populate in memory arrays -- // it will return the number of voxels added -- glm::vec3 treeRoot = glm::vec3(0,0,0); -- voxelsRendered = treeToArrays(tree->rootNode, treeRoot); -+ _voxelsUpdated = newTreeToArrays(_tree->rootNode); -+ if (_voxelsUpdated) { -+ _voxelsDirty=true; -+ } -+ - // copy the newly written data to the arrays designated for reading - copyWrittenDataToReadArrays(); - } - - void VoxelSystem::copyWrittenDataToReadArrays() { -- // lock on the buffer write lock so we can't modify the data when the GPU is reading it -- pthread_mutex_lock(&bufferWriteLock); -- // store a pointer to the current end so it doesn't change during copy -- GLfloat *endOfCurrentVerticesData = writeVerticesEndPointer; -- // copy the vertices and colors -- memcpy(readVerticesArray, writeVerticesArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLfloat)); -- memcpy(readColorsArray, writeColorsArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLubyte)); -- // set the read vertices end pointer to the correct spot so the GPU knows how much to pull -- readVerticesEndPointer = readVerticesArray + (endOfCurrentVerticesData - writeVerticesArray); -- pthread_mutex_unlock(&bufferWriteLock); -+ if (_voxelsDirty) { -+ // lock on the buffer write lock so we can't modify the data when the GPU is reading it -+ pthread_mutex_lock(&_bufferWriteLock); -+ int bytesOfVertices = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat); -+ int bytesOfColors = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLubyte); -+ memcpy(_readVerticesArray, _writeVerticesArray, bytesOfVertices); -+ memcpy(_readColorsArray, _writeColorsArray, bytesOfColors ); -+ pthread_mutex_unlock(&_bufferWriteLock); -+ } - } - --int VoxelSystem::treeToArrays(VoxelNode* currentNode, const glm::vec3& nodePosition) { -- int voxelsAdded = 0; -- float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE); -- glm::vec3 viewerPosition = _camera->getPosition(); //_viewerAvatar->getPosition(); -- -- // debug LOD code -- glm::vec3 debugNodePosition; -- copyFirstVertexForCode(currentNode->octalCode,(float*)&debugNodePosition); -- -- float distanceToVoxelCenter = sqrtf(powf(viewerPosition.x - nodePosition[0] - halfUnitForVoxel, 2) + -- 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); -- } -+int VoxelSystem::newTreeToArrays(VoxelNode* node) { -+ assert(_viewFrustum); // you must set up _viewFrustum before calling this -+ int voxelsUpdated = 0; -+ 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)); -+ -+ node->setShouldRender(shouldRender); -+ // let children figure out their renderness -+ for (int i = 0; i < 8; i++) { -+ if (node->children[i]) { -+ voxelsUpdated += newTreeToArrays(node->children[i]); - } - } -+ -+ // 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 -- // add our vertex and color information to the interleaved array -- if (voxelsAdded == 0 && currentNode->isColored()) { -- float startVertex[3]; -- copyFirstVertexForCode(currentNode->octalCode,(float*)&startVertex); -- float voxelScale = 1 / powf(2, *currentNode->octalCode); -+ // If this node has not yet been written to the array, then add it to the end of the array. -+ glBufferIndex nodeIndex; -+ if (node->isKnownBufferIndex()) { -+ nodeIndex = node->getBufferIndex(); -+ } else { -+ nodeIndex = _voxelsInArrays; -+ } -+ -+ _voxelDirtyArray[nodeIndex] = true; - - // 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++ ) { -- *writeVerticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); -- *(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->getColor()[j % 3]; -- -- writeVerticesEndPointer++; -+ GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); -+ GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); -+ *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); -+ *(writeColorsAt +j) = node->getColor()[j % 3]; -+ } -+ if (!node->isKnownBufferIndex()) { -+ node->setBufferIndex(nodeIndex); -+ _voxelsInArrays++; // our know vertices in the arrays - } -- voxelsAdded++; -+ voxelsUpdated++; -+ node->clearDirtyBit(); - } -- -- return voxelsAdded; -+ return voxelsUpdated; - } - - VoxelSystem* VoxelSystem::clone() const { -@@ -230,20 +224,30 @@ VoxelSystem* VoxelSystem::clone() const { - } - - void VoxelSystem::init() { -+ -+ // 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 -- 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]; -+ _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]; -+ GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; - - // populate the indicesArray - // 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++) { - // fill the indices array - int voxelIndexOffset = n * INDICES_PER_VOXEL; -- GLuint *currentIndicesPos = indicesArray + voxelIndexOffset; -+ GLuint* currentIndicesPos = indicesArray + voxelIndexOffset; - int startIndex = (n * VERTICES_PER_VOXEL); - - 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 *normalsArrayEndPointer = normalsArray; -+ GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; -+ GLfloat* normalsArrayEndPointer = normalsArray; - - // populate the normalsArray - for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) { -@@ -263,25 +267,25 @@ void VoxelSystem::init() { - } - - // VBO for the verticesArray -- glGenBuffers(1, &vboVerticesID); -- glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); -+ glGenBuffers(1, &_vboVerticesID); -+ glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); - - // VBO for the normalsArray -- glGenBuffers(1, &vboNormalsID); -- glBindBuffer(GL_ARRAY_BUFFER, vboNormalsID); -+ glGenBuffers(1, &_vboNormalsID); -+ glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); - glBufferData(GL_ARRAY_BUFFER, - VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, - normalsArray, GL_STATIC_DRAW); - - // VBO for colorsArray -- glGenBuffers(1, &vboColorsID); -- glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); -+ glGenBuffers(1, &_vboColorsID); -+ glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - 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); -- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); -+ glGenBuffers(1, &_vboIndicesID); -+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, - INDICES_PER_VOXEL * sizeof(GLuint) * MAX_VOXELS_PER_SYSTEM, - indicesArray, GL_STATIC_DRAW); -@@ -291,45 +295,68 @@ void VoxelSystem::init() { - delete[] normalsArray; - } - --void VoxelSystem::render() { -- -- glPushMatrix(); -- -- if (readVerticesEndPointer != readVerticesArray) { -- // try to lock on the buffer write -- // just avoid pulling new data if it is currently being written -- if (pthread_mutex_trylock(&bufferWriteLock) == 0) { -- -- glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); -- glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLfloat), readVerticesArray); -- -- glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); -- glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLubyte), readColorsArray); -- -- readVerticesEndPointer = readVerticesArray; -- -- pthread_mutex_unlock(&bufferWriteLock); -+void VoxelSystem::updateVBOs() { -+ if (_voxelsDirty) { -+ glBufferIndex segmentStart = 0; -+ glBufferIndex segmentEnd = 0; -+ -+ bool inSegment = false; -+ for (glBufferIndex i = 0; i < _voxelsInArrays; i++) { -+ if (!inSegment) { -+ if (_voxelDirtyArray[i]) { -+ segmentStart = i; -+ inSegment = true; -+ _voxelDirtyArray[i] = false; // consider us clean! -+ } -+ } else { -+ if (!_voxelDirtyArray[i] || (i == (_voxelsInArrays - 1)) ) { -+ segmentEnd = i; -+ inSegment = false; -+ int segmentLength = (segmentEnd - segmentStart) + 1; -+ -+ // vertices for segment - note: we might not need to do this -+ 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); -+ -+ // colors for segment -+ 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 - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - -- glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); -+ glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glVertexPointer(3, GL_FLOAT, 0, 0); - -- glBindBuffer(GL_ARRAY_BUFFER, vboNormalsID); -+ glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); - glNormalPointer(GL_FLOAT, 0, 0); - -- glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); -+ glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); - - // 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 * _voxelsInArrays, GL_UNSIGNED_INT, 0); - - // deactivate vertex and color arrays after drawing - glDisableClientState(GL_VERTEX_ARRAY); -@@ -350,12 +377,7 @@ void VoxelSystem::simulate(float deltaTime) { - - int VoxelSystem::_nodeCount = 0; - --bool VoxelSystem::randomColorOperation(VoxelNode* node, bool down, void* extraData) { -- -- // we do our operations on the way up! -- if (down) { -- return true; -- } -+bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) { - - _nodeCount++; - if (node->isColored()) { -@@ -370,17 +392,12 @@ bool VoxelSystem::randomColorOperation(VoxelNode* node, bool down, void* extraDa - - void VoxelSystem::randomizeVoxelColors() { - _nodeCount = 0; -- tree->recurseTreeWithOperation(randomColorOperation); -+ _tree->recurseTreeWithOperation(randomColorOperation); - printLog("setting randomized true color for %d nodes\n",_nodeCount); - setupNewVoxelsForDrawing(); - } - --bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, bool down, void* extraData) { -- -- // we do our operations on the way up! -- if (down) { -- return true; -- } -+bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, void* extraData) { - - _nodeCount++; - -@@ -395,18 +412,12 @@ bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, bool down, void* - - void VoxelSystem::falseColorizeRandom() { - _nodeCount = 0; -- tree->recurseTreeWithOperation(falseColorizeRandomOperation); -+ _tree->recurseTreeWithOperation(falseColorizeRandomOperation); - printLog("setting randomized false color for %d nodes\n",_nodeCount); - setupNewVoxelsForDrawing(); - } - --bool VoxelSystem::trueColorizeOperation(VoxelNode* node, bool down, void* extraData) { -- -- // we do our operations on the way up! -- if (down) { -- return true; -- } -- -+bool VoxelSystem::trueColorizeOperation(VoxelNode* node, void* extraData) { - _nodeCount++; - node->setFalseColored(false); - return true; -@@ -414,19 +425,13 @@ bool VoxelSystem::trueColorizeOperation(VoxelNode* node, bool down, void* extraD - - void VoxelSystem::trueColorize() { - _nodeCount = 0; -- tree->recurseTreeWithOperation(trueColorizeOperation); -+ _tree->recurseTreeWithOperation(trueColorizeOperation); - printLog("setting true color for %d nodes\n",_nodeCount); - setupNewVoxelsForDrawing(); - } - - // Will false colorize voxels that are not in view --bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void* extraData) { -- -- // we do our operations on the way up! -- if (down) { -- return true; -- } -- -+bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, void* extraData) { - const ViewFrustum* viewFrustum = (const ViewFrustum*) extraData; - - _nodeCount++; -@@ -448,25 +453,17 @@ bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void* - - void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) { - _nodeCount = 0; -- tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum); -+ _tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum); - printLog("setting in view false color for %d nodes\n",_nodeCount); - setupNewVoxelsForDrawing(); - } - - // Will false colorize voxels based on distance from view --bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool down, void* extraData) { -- -- // we do our operations on the way up! -- if (down) { -- return true; -- } -- -+bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, void* extraData) { - ViewFrustum* viewFrustum = (ViewFrustum*) extraData; - - // only do this for truly colored voxels... - if (node->isColored()) { -- -- // We need our distance for both up and down - glm::vec3 nodePosition; - float* startVertex = firstVertexForCode(node->octalCode); - nodePosition.x = startVertex[0]; -@@ -508,13 +505,7 @@ float VoxelSystem::_minDistance = FLT_MAX; - // 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 - // we wouldn't need to do two passes of the tree --bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, bool down, void* extraData) { -- -- // we do our operations on the way up! -- if (down) { -- return true; -- } -- -+bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, void* extraData) { - ViewFrustum* viewFrustum = (ViewFrustum*) extraData; - - // only do this for truly colored voxels... -@@ -538,7 +529,7 @@ bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, bool down, - powf(viewerPosition.y - nodePosition.y - halfUnitForVoxel, 2) + - powf(viewerPosition.z - nodePosition.z - halfUnitForVoxel, 2)); - -- // on way down, calculate the range of distances -+ // calculate the range of distances - if (distance > _maxDistance) { - _maxDistance = distance; - } -@@ -556,12 +547,14 @@ void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) { - - _maxDistance = 0.0; - _minDistance = FLT_MAX; -- tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum); -+ _tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum); - printLog("determining distance range for %d nodes\n",_nodeCount); - - _nodeCount = 0; - -- tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum); -+ _tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum); - printLog("setting in distance false color for %d nodes\n",_nodeCount); - setupNewVoxelsForDrawing(); - } -+ -+ -diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h -index f12cc75..04f9f8c 100644 ---- a/interface/src/VoxelSystem.h -+++ b/interface/src/VoxelSystem.h -@@ -29,12 +29,16 @@ public: - - int parseData(unsigned char* sourceBuffer, int numBytes); - VoxelSystem* clone() const; -+ -+ void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }; - - void init(); - void simulate(float deltaTime); - 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 setCamera(Camera* newCamera) { _camera = newCamera; }; - void loadVoxelsFile(const char* fileName,bool wantColorRandomizer); -@@ -57,36 +61,42 @@ public: - private: - // Operation functions for tree recursion methods - static int _nodeCount; -- static bool randomColorOperation(VoxelNode* node, bool down, void* extraData); -- static bool falseColorizeRandomOperation(VoxelNode* node, bool down, void* extraData); -- static bool trueColorizeOperation(VoxelNode* node, bool down, void* extraData); -- static bool falseColorizeInViewOperation(VoxelNode* node, bool down, void* extraData); -- static bool falseColorizeDistanceFromViewOperation(VoxelNode* node, bool down, void* extraData); -- static bool getDistanceFromViewRangeOperation(VoxelNode* node, bool down, void* extraData); -+ static bool randomColorOperation(VoxelNode* node, void* extraData); -+ static bool falseColorizeRandomOperation(VoxelNode* node, void* extraData); -+ static bool trueColorizeOperation(VoxelNode* node, void* extraData); -+ static bool falseColorizeInViewOperation(VoxelNode* node, void* extraData); -+ static bool falseColorizeDistanceFromViewOperation(VoxelNode* node, void* extraData); -+ static bool getDistanceFromViewRangeOperation(VoxelNode* node, void* extraData); - - // these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here - static float _maxDistance; - static float _minDistance; - -- int voxelsRendered; - Avatar* _viewerAvatar; - Camera* _camera; -- VoxelTree *tree; -- GLfloat *readVerticesArray; -- GLubyte *readColorsArray; -- GLfloat *readVerticesEndPointer; -- GLfloat *writeVerticesArray; -- GLubyte *writeColorsArray; -- GLfloat *writeVerticesEndPointer; -- GLuint vboVerticesID; -- GLuint vboNormalsID; -- GLuint vboColorsID; -- GLuint vboIndicesID; -- pthread_mutex_t bufferWriteLock; -- -- int treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosition); -+ VoxelTree* _tree; -+ GLfloat* _readVerticesArray; -+ GLubyte* _readColorsArray; -+ GLfloat* _writeVerticesArray; -+ GLubyte* _writeColorsArray; -+ bool* _voxelDirtyArray; -+ unsigned long _voxelsUpdated; -+ unsigned long _voxelsInArrays; -+ -+ GLuint _vboVerticesID; -+ GLuint _vboNormalsID; -+ GLuint _vboColorsID; -+ GLuint _vboIndicesID; -+ pthread_mutex_t _bufferWriteLock; -+ -+ ViewFrustum* _viewFrustum; -+ -+ int newTreeToArrays(VoxelNode *currentNode); - void setupNewVoxelsForDrawing(); - void copyWrittenDataToReadArrays(); -+ void updateVBOs(); -+ -+ bool _voxelsDirty; - }; - - #endif -diff --git a/interface/src/main.cpp b/interface/src/main.cpp -index 7ef1c49..b73d58f 100644 ---- a/interface/src/main.cpp -+++ b/interface/src/main.cpp -@@ -230,7 +230,7 @@ void displayStats(void) - drawtext(10, statsVerticalOffset + 49, 0.10f, 0, 1.0, 0, stats); - - 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()); - - voxelStats.str(""); -@@ -1612,6 +1612,8 @@ void audioMixerUpdate(in_addr_t newMixerAddress, in_port_t newMixerPort) { - - int main(int argc, const char * argv[]) - { -+ voxels.setViewFrustum(&::viewFrustum); -+ - shared_lib::printLog = & ::printLog; - voxels_lib::printLog = & ::printLog; - avatars_lib::printLog = & ::printLog; -@@ -1634,7 +1636,7 @@ int main(int argc, const char * argv[]) - } - - // 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"); - int ip = getLocalAddress(); - sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF)); -diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h -index 66ddbcb..2ba4d05 100644 ---- a/libraries/voxels/src/VoxelConstants.h -+++ b/libraries/voxels/src/VoxelConstants.h -@@ -21,4 +21,7 @@ const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; - const int INDICES_PER_VOXEL = 3 * 12; - const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; - -+typedef unsigned long int glBufferIndex; -+const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX; -+ - #endif -diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp -index c1527d3..6f8f1d7 100644 ---- a/libraries/voxels/src/VoxelNode.cpp -+++ b/libraries/voxels/src/VoxelNode.cpp -@@ -30,6 +30,10 @@ VoxelNode::VoxelNode() { - for (int i = 0; i < 8; i++) { - children[i] = NULL; - } -+ -+ _glBufferIndex = GLBUFFER_INDEX_UNKNOWN; -+ _isDirty = true; -+ _shouldRender = false; - } - - 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 { - - glm::vec3 corner; -@@ -59,16 +71,19 @@ void VoxelNode::getAABox(AABox& box) const { - } - - 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 -- // 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 -- // it to not-false-colored here! -- children[childIndex]->setFalseColored(false); -+ // 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 -+ // to-do to research this. But for now we'll use belt and suspenders and set -+ // it to not-false-colored here! -+ children[childIndex]->setFalseColored(false); - -- // give this child its octal code -- children[childIndex]->octalCode = childOctalCode(octalCode, childIndex); -+ // give this child its octal code -+ children[childIndex]->octalCode = childOctalCode(octalCode, childIndex); -+ _isDirty = true; -+ } - } - - // will average the child colors... -@@ -104,26 +119,35 @@ void VoxelNode::setColorFromAverageOfChildren() { - // the actual NO_FALSE_COLOR version are inline in the VoxelNode.h - #ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color - void VoxelNode::setFalseColor(colorPart red, colorPart green, colorPart blue) { -- _falseColored=true; -- _currentColor[0] = red; -- _currentColor[1] = green; -- _currentColor[2] = blue; -- _currentColor[3] = 1; // XXXBHG - False colors are always considered set -+ if (_falseColored != true || _currentColor[0] != red || _currentColor[1] != green || _currentColor[2] != blue) { -+ _falseColored=true; -+ _currentColor[0] = red; -+ _currentColor[1] = green; -+ _currentColor[2] = blue; -+ _currentColor[3] = 1; // XXXBHG - False colors are always considered set -+ _isDirty = true; -+ } - } - - void VoxelNode::setFalseColored(bool isFalseColored) { -- // if we were false colored, and are no longer false colored, then swap back -- if (_falseColored && !isFalseColored) { -- memcpy(&_currentColor,&_trueColor,sizeof(nodeColor)); -+ if (_falseColored != isFalseColored) { -+ // if we were false colored, and are no longer false colored, then swap back -+ if (_falseColored && !isFalseColored) { -+ memcpy(&_currentColor,&_trueColor,sizeof(nodeColor)); -+ } -+ _falseColored = isFalseColored; -+ _isDirty = true; - } -- _falseColored = isFalseColored; - }; - - - void VoxelNode::setColor(const nodeColor& color) { -- memcpy(&_trueColor,&color,sizeof(nodeColor)); -- if (!_falseColored) { -- memcpy(&_currentColor,&color,sizeof(nodeColor)); -+ if (_trueColor[0] != color[0] || _trueColor[1] != color[1] || _trueColor[2] != color[2]) { -+ memcpy(&_trueColor,&color,sizeof(nodeColor)); -+ if (!_falseColored) { -+ memcpy(&_currentColor,&color,sizeof(nodeColor)); -+ } -+ _isDirty = true; - } - } - #endif -@@ -199,7 +223,6 @@ void VoxelNode::printDebugDetails(const char* label) const { - printOctalCode(octalCode); - } - -- - bool VoxelNode::isInView(const ViewFrustum& viewFrustum) const { - AABox box; - getAABox(box); -diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h -index 4cda55f..cbd9b8a 100644 ---- a/libraries/voxels/src/VoxelNode.h -+++ b/libraries/voxels/src/VoxelNode.h -@@ -11,6 +11,7 @@ - - #include "AABox.h" - #include "ViewFrustum.h" -+#include "VoxelConstants.h" - - typedef unsigned char colorPart; - typedef unsigned char nodeColor[4]; -@@ -22,6 +23,11 @@ private: - nodeColor _currentColor; - bool _falseColored; - #endif -+ -+ glBufferIndex _glBufferIndex; -+ bool _isDirty; -+ bool _shouldRender; -+ - public: - VoxelNode(); - ~VoxelNode(); -@@ -40,6 +46,18 @@ public: - bool isLeaf() const; - void getAABox(AABox& box) 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; }; -+ -+ // whether or not we should render -+ void setShouldRender(bool shouldRender); -+ bool getShouldRender() const { return _shouldRender; } -+ - - #ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color - void setFalseColor(colorPart red, colorPart green, colorPart blue); -diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp -index cbbcced..3ff14b5 100644 ---- a/libraries/voxels/src/VoxelTree.cpp -+++ b/libraries/voxels/src/VoxelTree.cpp -@@ -58,16 +58,13 @@ void VoxelTree::recurseTreeWithOperation(RecurseVoxelTreeOperation operation, vo - - // Recurses voxel node with an operation function - 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,true,extraData)) { -- for (int i = 0; i < sizeof(node->children)/sizeof(node->children[0]); i++) { -+ if (operation(node, extraData)) { -+ for (int i = 0; i < sizeof(node->children) / sizeof(node->children[0]); i++) { - VoxelNode* child = node->children[i]; - if (child) { -- recurseNodeWithOperation(child,operation,extraData); -+ recurseNodeWithOperation(child, operation, extraData); - } - } -- // call operation on way back up -- operation(node,false,extraData); - } - } - -diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h -index ac3c762..7f5a6b8 100644 ---- a/libraries/voxels/src/VoxelTree.h -+++ b/libraries/voxels/src/VoxelTree.h -@@ -16,7 +16,7 @@ - #include "VoxelNodeBag.h" - - // Callback function, for recuseTreeWithOperation --typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, bool down, void* extraData); -+typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, void* extraData); - - class VoxelTree { - public: -diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp -index 716a4e9..9ab5675 100644 ---- a/voxel-server/src/main.cpp -+++ b/voxel-server/src/main.cpp -@@ -38,7 +38,7 @@ const float DEATH_STAR_RADIUS = 4.0; - const float MAX_CUBE = 0.05f; - - 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; - -@@ -68,11 +68,9 @@ void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) { - } - - int _nodeCount=0; --bool countVoxelsOperation(VoxelNode* node, bool down, void* extraData) { -- if (down) { -- if (node->isColored()){ -- _nodeCount++; -- } -+bool countVoxelsOperation(VoxelNode* node, void* extraData) { -+ if (node->isColored()){ -+ _nodeCount++; - } - return true; // keep going - } -@@ -80,7 +78,7 @@ bool countVoxelsOperation(VoxelNode* node, bool down, void* extraData) { - void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) { - 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); - printf("one sphere added...\n"); From cfcfacfbdbfe20a34224cfa2d369855a03ff26fd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 1 May 2013 18:25:42 -0700 Subject: [PATCH 3/6] cleanup --- libraries/voxels/src/VoxelNode.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index cbd9b8af47..26edb87e79 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -23,11 +23,9 @@ private: nodeColor _currentColor; bool _falseColored; #endif - glBufferIndex _glBufferIndex; bool _isDirty; bool _shouldRender; - public: VoxelNode(); ~VoxelNode(); @@ -46,19 +44,14 @@ public: bool isLeaf() const; void getAABox(AABox& box) 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; }; - - // whether or not we should render void setShouldRender(bool shouldRender); bool getShouldRender() const { return _shouldRender; } - #ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color void setFalseColor(colorPart red, colorPart green, colorPart blue); void setFalseColored(bool isFalseColored); From 62e7c0383bd92eec1f9e4c45cea87751c98fa707 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 1 May 2013 18:31:05 -0700 Subject: [PATCH 4/6] cleaned up some code for distanceToCamera() --- interface/src/VoxelSystem.cpp | 63 ++--------------------------------- 1 file changed, 2 insertions(+), 61 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index b8157d0943..90a13e98ab 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -299,7 +299,6 @@ void VoxelSystem::updateVBOs() { if (_voxelsDirty) { glBufferIndex segmentStart = 0; glBufferIndex segmentEnd = 0; - bool inSegment = false; for (glBufferIndex i = 0; i < _voxelsInArrays; i++) { if (!inSegment) { @@ -313,20 +312,14 @@ void VoxelSystem::updateVBOs() { segmentEnd = i; inSegment = false; int segmentLength = (segmentEnd - segmentStart) + 1; - - // vertices for segment - note: we might not need to do this 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); - - // colors for segment 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); } @@ -378,7 +371,6 @@ void VoxelSystem::simulate(float deltaTime) { int VoxelSystem::_nodeCount = 0; bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) { - _nodeCount++; if (node->isColored()) { nodeColor newColor = { 0,0,0,1 }; @@ -398,15 +390,12 @@ void VoxelSystem::randomizeVoxelColors() { } bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, void* extraData) { - _nodeCount++; - // always false colorize unsigned char newR = randomColorValue(150); unsigned char newG = randomColorValue(150); unsigned char newB = randomColorValue(150); node->setFalseColor(newR,newG,newB); - return true; // keep going! } @@ -433,12 +422,8 @@ void VoxelSystem::trueColorize() { // Will false colorize voxels that are not in view bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, void* extraData) { const ViewFrustum* viewFrustum = (const ViewFrustum*) extraData; - _nodeCount++; - - // only do this for truely colored voxels... if (node->isColored()) { - // If the voxel is outside of the view frustum, then false color it red if (!node->isInView(*viewFrustum)) { // Out of view voxels are colored RED unsigned char newR = 255; @@ -447,7 +432,6 @@ bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, void* extraData) node->setFalseColor(newR,newG,newB); } } - return true; // keep going! } @@ -461,29 +445,9 @@ void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) { // Will false colorize voxels based on distance from view bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, void* extraData) { ViewFrustum* viewFrustum = (ViewFrustum*) extraData; - - // only do this for truly colored voxels... if (node->isColored()) { - 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 + float distance = node->distanceToCamera(*viewFrustum); _nodeCount++; - float distanceRatio = (_minDistance==_maxDistance) ? 1 : (distance - _minDistance)/(_maxDistance - _minDistance); // We want to colorize this in 16 bug chunks of color @@ -507,28 +471,9 @@ float VoxelSystem::_minDistance = FLT_MAX; // we wouldn't need to do two passes of the tree bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, void* extraData) { ViewFrustum* viewFrustum = (ViewFrustum*) extraData; - // only do this for truly colored voxels... if (node->isColored()) { - - // 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)); - + float distance = node->distanceToCamera(*viewFrustum); // calculate the range of distances if (distance > _maxDistance) { _maxDistance = distance; @@ -536,7 +481,6 @@ bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, void* extra if (distance < _minDistance) { _minDistance = distance; } - _nodeCount++; } return true; // keep going! @@ -544,14 +488,11 @@ bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, void* extra void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) { _nodeCount = 0; - _maxDistance = 0.0; _minDistance = FLT_MAX; _tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum); printLog("determining distance range for %d nodes\n",_nodeCount); - _nodeCount = 0; - _tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum); printLog("setting in distance false color for %d nodes\n",_nodeCount); setupNewVoxelsForDrawing(); From 015fd05e62b4e80207c1efa7d7d43490d43949a5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 1 May 2013 18:37:14 -0700 Subject: [PATCH 5/6] code cleanup --- interface/src/VoxelSystem.cpp | 40 +++++++++++------------------------ interface/src/VoxelSystem.h | 2 +- 2 files changed, 13 insertions(+), 29 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 90a13e98ab..76fda4f942 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -364,19 +364,12 @@ void VoxelSystem::render() { glPopMatrix(); } -void VoxelSystem::simulate(float deltaTime) { - -} - int VoxelSystem::_nodeCount = 0; bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) { _nodeCount++; if (node->isColored()) { - nodeColor newColor = { 0,0,0,1 }; - newColor[0] = randomColorValue(150); - newColor[1] = randomColorValue(150); - newColor[1] = randomColorValue(150); + nodeColor newColor = { randomColorValue(150), randomColorValue(150), randomColorValue(150), 1 }; node->setColor(newColor); } return true; @@ -385,24 +378,21 @@ bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) { void VoxelSystem::randomizeVoxelColors() { _nodeCount = 0; _tree->recurseTreeWithOperation(randomColorOperation); - printLog("setting randomized true color for %d nodes\n",_nodeCount); + printLog("setting randomized true color for %d nodes\n", _nodeCount); setupNewVoxelsForDrawing(); } bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, void* extraData) { _nodeCount++; // always false colorize - unsigned char newR = randomColorValue(150); - unsigned char newG = randomColorValue(150); - unsigned char newB = randomColorValue(150); - node->setFalseColor(newR,newG,newB); + node->setFalseColor(randomColorValue(150), randomColorValue(150), randomColorValue(150)); return true; // keep going! } void VoxelSystem::falseColorizeRandom() { _nodeCount = 0; _tree->recurseTreeWithOperation(falseColorizeRandomOperation); - printLog("setting randomized false color for %d nodes\n",_nodeCount); + printLog("setting randomized false color for %d nodes\n", _nodeCount); setupNewVoxelsForDrawing(); } @@ -415,7 +405,7 @@ bool VoxelSystem::trueColorizeOperation(VoxelNode* node, void* extraData) { void VoxelSystem::trueColorize() { _nodeCount = 0; _tree->recurseTreeWithOperation(trueColorizeOperation); - printLog("setting true color for %d nodes\n",_nodeCount); + printLog("setting true color for %d nodes\n", _nodeCount); setupNewVoxelsForDrawing(); } @@ -426,10 +416,7 @@ bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, void* extraData) if (node->isColored()) { if (!node->isInView(*viewFrustum)) { // Out of view voxels are colored RED - unsigned char newR = 255; - unsigned char newG = 0; - unsigned char newB = 0; - node->setFalseColor(newR,newG,newB); + node->setFalseColor(255, 0, 0); } } return true; // keep going! @@ -438,7 +425,7 @@ bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, void* extraData) void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) { _nodeCount = 0; _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(); } @@ -448,17 +435,14 @@ bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, void* if (node->isColored()) { float distance = node->distanceToCamera(*viewFrustum); _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 const unsigned char maxColor = 255; const unsigned char colorBands = 16; const unsigned char gradientOver = 128; - unsigned char colorBand = (colorBands*distanceRatio); - unsigned char newR = (colorBand*(gradientOver/colorBands))+(maxColor-gradientOver); - unsigned char newG = 0; - unsigned char newB = 0; - node->setFalseColor(newR,newG,newB); + unsigned char colorBand = (colorBands * distanceRatio); + node->setFalseColor((colorBand * (gradientOver / colorBands)) + (maxColor - gradientOver), 0, 0); } return true; // keep going! } @@ -491,10 +475,10 @@ void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) { _maxDistance = 0.0; _minDistance = FLT_MAX; _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; _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(); } diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 04f9f8ceb7..e6798f9fd1 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -33,7 +33,7 @@ public: void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }; void init(); - void simulate(float deltaTime); + void simulate(float deltaTime) { }; void render(); unsigned long getVoxelsUpdated() const {return _voxelsUpdated;}; From 0f716279230919935430dde0090ef0244ac38bcd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 1 May 2013 21:22:41 -0700 Subject: [PATCH 6/6] fixed local mode --- interface/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 055bf73c85..08b1666d05 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -1633,7 +1633,7 @@ int main(int argc, const char * argv[]) } // Handle Local Domain testing with the --local command line - if (true || cmdOptionExists(argc, argv, "--local")) { + if (cmdOptionExists(argc, argv, "--local")) { printLog("Local Domain MODE!\n"); int ip = getLocalAddress(); sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));