History

First cut are removing out of view voxels and switch to using PerformanceWarnings

ZappoMan committed 13 years ago

Commit 7ba9d4a1 parent e0d040a2 files · +83 −63Browse files

Showing the changes to interface/src/VoxelSystem.cpp (1 of 2 files). Show all

Unified · Split

interface/src/VoxelSystem.cpp+74−63
@@ -15,6 +15,7 @@ · 14 unmodified lines
15#include <fstream> // to load voxels from file15#include <fstream> // to load voxels from file
16#include <SharedUtil.h>16#include <SharedUtil.h>
17#include <PacketHeaders.h>17#include <PacketHeaders.h>
18#include <PerfStat.h>
18#include <OctalCode.h>19#include <OctalCode.h>
19#include <pthread.h>20#include <pthread.h>
20#include "Log.h"21#include "Log.h"
@@ -44,6 +45,7 @@ VoxelSystem::VoxelSystem() { · 23 unmodified lines
44 _voxelsInArrays = _voxelsUpdated = 0;45 _voxelsInArrays = _voxelsUpdated = 0;
45 _tree = new VoxelTree();46 _tree = new VoxelTree();
46 pthread_mutex_init(&_bufferWriteLock, NULL);47 pthread_mutex_init(&_bufferWriteLock, NULL);
48 pthread_mutex_init(&_voxelCleanupLock, NULL);
47}49}
48 50
49VoxelSystem::~VoxelSystem() {51VoxelSystem::~VoxelSystem() {
@@ -54,6 +56,7 @@ VoxelSystem::~VoxelSystem() { · 4 unmodified lines
54 delete[] _voxelDirtyArray;56 delete[] _voxelDirtyArray;
55 delete _tree;57 delete _tree;
56 pthread_mutex_destroy(&_bufferWriteLock);58 pthread_mutex_destroy(&_bufferWriteLock);
59 pthread_mutex_destroy(&_voxelCleanupLock);
57}60}
58 61
59void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {62void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
@@ -98,24 +101,13 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 38 unmodified lines
98 switch(command) {101 switch(command) {
99 case PACKET_HEADER_VOXEL_DATA:102 case PACKET_HEADER_VOXEL_DATA:
100 {103 {
101 double start = usecTimestampNow();104 PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()");
102 // ask the VoxelTree to read the bitstream into the tree105 // ask the VoxelTree to read the bitstream into the tree
103 _tree->readBitstreamToTree(voxelData, numBytes - 1);106 _tree->readBitstreamToTree(voxelData, numBytes - 1);
104 if (_renderWarningsOn && _tree->getNodesChangedFromBitstream()) {107 if (_renderWarningsOn && _tree->getNodesChangedFromBitstream()) {
105 printLog("readBitstreamToTree()... getNodesChangedFromBitstream=%ld _tree->isDirty()=%s \n",108 printLog("readBitstreamToTree()... getNodesChangedFromBitstream=%ld _tree->isDirty()=%s \n",
106 _tree->getNodesChangedFromBitstream(), (_tree->isDirty() ? "yes" : "no") );109 _tree->getNodesChangedFromBitstream(), (_tree->isDirty() ? "yes" : "no") );
107 }110 }
108
109 double end = usecTimestampNow();
110 double elapsedmsec = (end - start)/1000.0;
111 if (_renderWarningsOn && elapsedmsec > 1) {
112 if (elapsedmsec > 1000) {
113 double elapsedsec = (end - start)/1000000.0;
114 printLog("WARNING! readBitstreamToTree() took %lf seconds\n",elapsedsec);
115 } else {
116 printLog("WARNING! readBitstreamToTree() took %lf milliseconds\n",elapsedmsec);
117 }
118 }
119 }111 }
120 break;112 break;
121 case PACKET_HEADER_ERASE_VOXEL:113 case PACKET_HEADER_ERASE_VOXEL:
@@ -153,14 +145,19 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 31 unmodified lines
153}145}
154 146
155void VoxelSystem::setupNewVoxelsForDrawing() {147void VoxelSystem::setupNewVoxelsForDrawing() {
148 PerformanceWarning warn(_renderWarningsOn, "copyWrittenDataToReadArrays()"); // would like to include _voxelsInArrays, _voxelsUpdated
156 double start = usecTimestampNow();149 double start = usecTimestampNow();
157
158 double sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished);150 double sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished);
159 151
160 if (sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed,SIXTY_FPS_IN_MILLISECONDS)) {152 if (sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed,SIXTY_FPS_IN_MILLISECONDS)) {
161 return; // bail early, it hasn't been long enough since the last time we ran153 return; // bail early, it hasn't been long enough since the last time we ran
162 }154 }
163 155
156 // If the view frustum has changed, since last time, then remove nodes that are out of view
157 //if (hasViewChanged()) {
158 // removeOutOfView();
159 //}
160
164 if (_tree->isDirty()) {161 if (_tree->isDirty()) {
165 _callsToTreesToArrays++;162 _callsToTreesToArrays++;
166 _voxelsUpdated = newTreeToArrays(_tree->rootNode);163 _voxelsUpdated = newTreeToArrays(_tree->rootNode);
@@ -179,21 +176,12 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 12 unmodified lines
179 176
180 double end = usecTimestampNow();177 double end = usecTimestampNow();
181 double elapsedmsec = (end - start)/1000.0;178 double elapsedmsec = (end - start)/1000.0;
182 if (_renderWarningsOn && elapsedmsec > 1) {
183 if (elapsedmsec > 1000) {
184 double elapsedsec = (end - start)/1000000.0;
185 printLog("WARNING! newTreeToArrays() took %lf seconds %ld voxels updated\n", elapsedsec, _voxelsUpdated);
186 } else {
187 printLog("WARNING! newTreeToArrays() took %lf milliseconds %ld voxels updated\n", elapsedmsec, _voxelsUpdated);
188 }
189 }
190
191 _setupNewVoxelsForDrawingLastFinished = end;179 _setupNewVoxelsForDrawingLastFinished = end;
192 _setupNewVoxelsForDrawingLastElapsed = elapsedmsec;180 _setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
193}181}
194 182
195void VoxelSystem::copyWrittenDataToReadArrays() {183void VoxelSystem::copyWrittenDataToReadArrays() {
196 double start = usecTimestampNow();184 PerformanceWarning warn(_renderWarningsOn, "copyWrittenDataToReadArrays()"); // would like to include _voxelsInArrays, _voxelsUpdated
197 if (_voxelsDirty && _voxelsUpdated) {185 if (_voxelsDirty && _voxelsUpdated) {
198 // lock on the buffer write lock so we can't modify the data when the GPU is reading it186 // lock on the buffer write lock so we can't modify the data when the GPU is reading it
199 pthread_mutex_lock(&_bufferWriteLock);187 pthread_mutex_lock(&_bufferWriteLock);
@@ -203,18 +191,6 @@ void VoxelSystem::copyWrittenDataToReadArrays() { · 3 unmodified lines
203 memcpy(_readColorsArray, _writeColorsArray, bytesOfColors );191 memcpy(_readColorsArray, _writeColorsArray, bytesOfColors );
204 pthread_mutex_unlock(&_bufferWriteLock);192 pthread_mutex_unlock(&_bufferWriteLock);
205 }193 }
206 double end = usecTimestampNow();
207 double elapsedmsec = (end - start)/1000.0;
208 if (_renderWarningsOn && elapsedmsec > 1) {
209 if (elapsedmsec > 1000) {
210 double elapsedsec = (end - start)/1000000.0;
211 printLog("WARNING! copyWrittenDataToReadArrays() took %lf seconds for %ld voxels %ld updated\n",
212 elapsedsec, _voxelsInArrays, _voxelsUpdated);
213 } else {
214 printLog("WARNING! copyWrittenDataToReadArrays() took %lf milliseconds for %ld voxels %ld updated\n",
215 elapsedmsec, _voxelsInArrays, _voxelsUpdated);
216 }
217 }
218}194}
219 195
220int VoxelSystem::newTreeToArrays(VoxelNode* node) {196int VoxelSystem::newTreeToArrays(VoxelNode* node) {
@@ -301,6 +277,7 @@ void VoxelSystem::init() { · 80 unmodified lines
301 // When we change voxels representations in the arrays, we'll update this277 // When we change voxels representations in the arrays, we'll update this
302 _voxelsDirty = false;278 _voxelsDirty = false;
303 _voxelsInArrays = 0;279 _voxelsInArrays = 0;
280 _unusedArraySpace = 0;
304 281
305 // we will track individual dirty sections with this array of bools282 // we will track individual dirty sections with this array of bools
306 _voxelDirtyArray = new bool[MAX_VOXELS_PER_SYSTEM];283 _voxelDirtyArray = new bool[MAX_VOXELS_PER_SYSTEM];
@@ -369,7 +346,7 @@ void VoxelSystem::init() { · 62 unmodified lines
369}346}
370 347
371void VoxelSystem::updateVBOs() {348void VoxelSystem::updateVBOs() {
372 double start = usecTimestampNow();349 PerformanceWarning warn(_renderWarningsOn, "updateVBOs()"); // would like to include _callsToTreesToArrays
373 if (_voxelsDirty) {350 if (_voxelsDirty) {
374 glBufferIndex segmentStart = 0;351 glBufferIndex segmentStart = 0;
375 glBufferIndex segmentEnd = 0;352 glBufferIndex segmentEnd = 0;
@@ -401,28 +378,13 @@ void VoxelSystem::updateVBOs() { · 25 unmodified lines
401 }378 }
402 _voxelsDirty = false;379 _voxelsDirty = false;
403 }380 }
404 double end = usecTimestampNow();
405 double elapsedmsec = (end - start)/1000.0;
406 if (_renderWarningsOn && elapsedmsec > 1) {
407 if (elapsedmsec > 1) {
408 if (elapsedmsec > 1000) {
409 double elapsedsec = (end - start)/1000000.0;
410 printLog("WARNING! updateVBOs() took %lf seconds after %d calls to newTreeToArrays()\n",
411 elapsedsec, _callsToTreesToArrays);
412 } else {
413 printLog("WARNING! updateVBOs() took %lf milliseconds after %d calls to newTreeToArrays()\n",
414 elapsedmsec, _callsToTreesToArrays);
415 }
416 } else {
417 printLog("WARNING! updateVBOs() called after %d calls to newTreeToArrays()\n",_callsToTreesToArrays);
418 }
419 }
420 _callsToTreesToArrays = 0; // clear it381 _callsToTreesToArrays = 0; // clear it
421}382}
422 383
423void VoxelSystem::render() {384void VoxelSystem::render() {
424 double start = usecTimestampNow();385 PerformanceWarning warn(_renderWarningsOn, "render()");
425 glPushMatrix();386 glPushMatrix();
387 //cleanupRemovedVoxels();
426 updateVBOs();388 updateVBOs();
427 // tell OpenGL where to find vertex and color information389 // tell OpenGL where to find vertex and color information
428 glEnableClientState(GL_VERTEX_ARRAY);390 glEnableClientState(GL_VERTEX_ARRAY);
@@ -454,16 +416,6 @@ void VoxelSystem::render() { · 25 unmodified lines
454 416
455 // scale back down to 1 so heads aren't massive417 // scale back down to 1 so heads aren't massive
456 glPopMatrix();418 glPopMatrix();
457 double end = usecTimestampNow();
458 double elapsedmsec = (end - start)/1000.0;
459 if (_renderWarningsOn && elapsedmsec > 1) {
460 if (elapsedmsec > 1000) {
461 double elapsedsec = (end - start)/1000000.0;
462 printLog("WARNING! render() took %lf seconds\n",elapsedsec);
463 } else {
464 printLog("WARNING! render() took %lf milliseconds\n",elapsedmsec);
465 }
466 }
467}419}
468 420
469int VoxelSystem::_nodeCount = 0;421int VoxelSystem::_nodeCount = 0;
@@ -591,4 +543,63 @@ void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) { · 121 unmodified lines
591 setupNewVoxelsForDrawing();543 setupNewVoxelsForDrawing();
592}544}
593 545
546// "Remove" voxels from the tree that are not in view. We don't actually delete them,
547// we remove them from the tree and place them into a holding area for later deletion
548int removedCount;
549bool VoxelSystem::removeOutOfViewOperation(VoxelNode* node, void* extraData) {
550 VoxelSystem* thisVoxelSystem = (VoxelSystem*) extraData;
551 _nodeCount++;
552 // Need to operate on our child nodes, so we can remove them
553 for (int i = 0; i < 8; i++) {
554 VoxelNode* childNode = node->getChildAtIndex(i);
555 if (childNode && !childNode->isInView(*thisVoxelSystem->_viewFrustum)) {
556 node->removeChildAtIndex(i);
557 removedCount++;
558
559 // Note: VoxelNodeBag is more expensive than we need, because it checks octal code matches,
560 // we really just want a simple bag that checks pointers only, consider switching
561 thisVoxelSystem->_removedVoxels.insert(childNode);
562 }
563 }
564 return true; // keep going!
565}
594 566
567bool VoxelSystem::hasViewChanged() {
568 bool result = false; // assume the best
569 if (_viewFrustum && !_lastKnowViewFrustum.matches(_viewFrustum)) {
570 result = true;
571 _lastKnowViewFrustum = *_viewFrustum; // save last known
572 }
573 return result;
574}
575
576void VoxelSystem::removeOutOfView() {
577 PerformanceWarning warn(_renderWarningsOn, "removeOutOfView()"); // would like to include removedCount, _nodeCount, _removedVoxels.count()
578 pthread_mutex_lock(&_voxelCleanupLock);
579 _nodeCount = 0;
580 removedCount = 0;
581 _tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)this);
582 pthread_mutex_unlock(&_voxelCleanupLock);
583}
584
585// Deletes the VoxelNodes from the _removedVoxels bag, but also cleans up those items from the vertex arrays
586void VoxelSystem::cleanupRemovedVoxels() {
587 if (!pthread_mutex_trylock(&_voxelCleanupLock)) {
588 while (!_removedVoxels.isEmpty()){
589 VoxelNode* node = _removedVoxels.extract();
590 // If the voxel is in the vertex, and it was previously rendered, then set it's vertices to "hidden"
591 if (node->isKnownBufferIndex() && node->getShouldRender()) {
592 unsigned long nodeIndex = node->getBufferIndex();
593 _voxelDirtyArray[nodeIndex] = true;
594 for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) {
595 GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL);
596 *(writeVerticesAt+j) = FLT_MAX;
597 }
598 _voxelsDirty = true; // yep
599 }
600 _unusedArraySpace++; // track this so we can blow away our arrays if they get too much
601 delete node; // actually delete the node
602 }
603 pthread_mutex_unlock(&_voxelCleanupLock);
604 }
605}