History

Optimized removeOutOfView() - don't recurse down trees that are fully INSIDE of the view frustum, because those nodes are guaranteed to also be INSIDE - changes to extraData of the recurse operation to make this possible - adding debug stats to track how many nodes are inside, outside, intersect - change call to removeOutOfView() to not call if last elapsed time has not yet passed since last call (similar to treeToArrays() logic)

ZappoMan committed 13 years ago

Commit 70557cd1 parent 66e416d2 files · +74 −10Browse files

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

Unified · Split

interface/src/VoxelSystem.cpp+73−10
@@ -146,9 +146,11 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 145 unmodified lines
146146 double sinceLastViewCulling = (start - _lastViewCulling) / 1000.0;
147147
148148 // If the view frustum has changed, since last time, then remove nodes that are out of view
149− if ((sinceLastViewCulling >= VIEW_CULLING_RATE_IN_MILLISECONDS) && hasViewChanged()) {
149+ if ((sinceLastViewCulling >= std::max(_lastViewCullingElapsed,VIEW_CULLING_RATE_IN_MILLISECONDS)) && hasViewChanged()) {
150150 _lastViewCulling = start;
151151 removeOutOfView();
152+ double endViewCulling = usecTimestampNow();
153+ _lastViewCullingElapsed = (endViewCulling - start)/1000.0;
152154 }
153155
154156 if (_tree->isDirty()) {
@@ -294,7 +296,7 @@ void VoxelSystem::init() { · 139 unmodified lines
294296 _callsToTreesToArrays = 0;
295297 _setupNewVoxelsForDrawingLastFinished = 0;
296298 _setupNewVoxelsForDrawingLastElapsed = 0;
297− _lastViewCulling = 0;
299+ _lastViewCullingElapsed = _lastViewCulling = 0;
298300
299301 // When we change voxels representations in the arrays, we'll update this
300302 _voxelsDirty = false;
@@ -583,17 +585,71 @@ void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) { · 282 unmodified lines
583585 setupNewVoxelsForDrawing();
584586 }
585587
588+// combines the removeOutOfView args into a single class
589+class removeOutOfViewArgs {
590+public:
591+ VoxelSystem* thisVoxelSystem;
592+ VoxelNodeBag dontRecurseBag;
593+ unsigned long nodesScanned;
594+ unsigned long nodesRemoved;
595+ unsigned long nodesInside;
596+ unsigned long nodesIntersect;
597+ unsigned long nodesOutside;
598+
599+ removeOutOfViewArgs(VoxelSystem* voxelSystem) :
600+ thisVoxelSystem(voxelSystem),
601+ dontRecurseBag(),
602+ nodesScanned(0),
603+ nodesRemoved(0),
604+ nodesInside(0),
605+ nodesIntersect(0),
606+ nodesOutside(0)
607+ { }
608+};
609+
586610 // "Remove" voxels from the tree that are not in view. We don't actually delete them,
587611 // we remove them from the tree and place them into a holding area for later deletion
588612 bool VoxelSystem::removeOutOfViewOperation(VoxelNode* node, void* extraData) {
589− VoxelSystem* thisVoxelSystem = (VoxelSystem*) extraData;
590− _nodeCount++;
613+ removeOutOfViewArgs* args = (removeOutOfViewArgs*)extraData;
614+
615+ // If our node was previously added to the don't recurse bag, then return false to
616+ // stop the further recursion. This means that the whole node and it's children are
617+ // known to be in view, so don't recurse them
618+ if (args->dontRecurseBag.contains(node)) {
619+ args->dontRecurseBag.remove(node);
620+ return false; // stop recursion
621+ }
622+
623+ VoxelSystem* thisVoxelSystem = args->thisVoxelSystem;
624+ args->nodesScanned++;
591625 // Need to operate on our child nodes, so we can remove them
592626 for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
593627 VoxelNode* childNode = node->getChildAtIndex(i);
594− if (childNode && !childNode->isInView(*thisVoxelSystem->_viewFrustum)) {
595− node->removeChildAtIndex(i);
596− thisVoxelSystem->_removedVoxels.insert(childNode);
628+ if (childNode) {
629+ ViewFrustum::location inFrustum = childNode->inFrustum(*thisVoxelSystem->_viewFrustum);
630+ switch (inFrustum) {
631+ case ViewFrustum::OUTSIDE: {
632+ args->nodesOutside++;
633+ args->nodesRemoved++;
634+ node->removeChildAtIndex(i);
635+ thisVoxelSystem->_removedVoxels.insert(childNode);
636+ // by removing the child, it will not get recursed!
637+ } break;
638+ case ViewFrustum::INSIDE: {
639+ // if the child node is fully INSIDE the view, then there's no need to recurse it
640+ // because we know all it's children will also be in the view, so we want to
641+ // tell the caller to NOT recurse this child
642+ args->nodesInside++;
643+ args->dontRecurseBag.insert(childNode);
644+ } break;
645+ case ViewFrustum::INTERSECT: {
646+ // if the child node INTERSECTs the view, then we don't want to remove it because
647+ // it is at least partially in view. But we DO want to recurse the children because
648+ // some of them may not be in view... nothing specifically to do, just keep iterating
649+ // the children
650+ args->nodesIntersect++;
651+ } break;
652+ }
597653 }
598654 }
599655 return true; // keep going!
@@ -609,7 +665,14 @@ bool VoxelSystem::hasViewChanged() { · 9 unmodified lines
609665 }
610666
611667 void VoxelSystem::removeOutOfView() {
612− PerformanceWarning warn(_renderWarningsOn, "removeOutOfView()"); // would like to include removedCount, _nodeCount, _removedVoxels.count()
613− _nodeCount = 0;
614− _tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)this);
668+ PerformanceWarning warn(_renderWarningsOn, "removeOutOfView()");
669+ removeOutOfViewArgs args(this);
670+ _tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)&args);
671+
672+ if (_renderWarningsOn) {
673+ printLog("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld bag.count()=%d \n",
674+ args.nodesScanned, args.nodesRemoved, args.nodesInside,
675+ args.nodesIntersect, args.nodesOutside, args.dontRecurseBag.count()
676+ );
677+ }
615678 }