From e2d22a8e2144bda8b8bb5eab37abd3c97296e47e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 12 Jun 2013 01:16:46 -0700 Subject: [PATCH] latest cut at occlusion culling --- interface/src/Application.cpp | 11 ++++- interface/src/VoxelSystem.cpp | 37 ++++++++++++++-- interface/src/VoxelSystem.h | 2 + libraries/voxels/src/CoverageMap.cpp | 7 ++- libraries/voxels/src/CoverageMap.h | 4 +- libraries/voxels/src/VoxelProjectedShadow.cpp | 11 +++++ libraries/voxels/src/VoxelProjectedShadow.h | 3 +- libraries/voxels/src/VoxelTree.cpp | 43 ++++++++++++++++++- libraries/voxels/src/VoxelTree.h | 5 +++ 9 files changed, 115 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d97e488d90..5dd9da7fa2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -60,6 +60,8 @@ #include "renderer/ProgramObject.h" #include "ui/TextRenderer.h" +#include + using namespace std; const bool TESTING_AVATAR_TOUCH = false; @@ -965,7 +967,6 @@ void Application::doFalseColorizeInView() { } void Application::doFalseColorizeOccluded() { - _debugShowVirtualOccluders->setChecked(true); _voxels.falseColorizeOccluded(); } @@ -1912,6 +1913,9 @@ glm::vec2 Application::getScreenPoint(glm::vec3 voxelPoint) { void Application::renderVirtualOccluders() { if (_debugShowVirtualOccluders->isChecked()) { + CoverageMap map(BoundingBox(glm::vec2(-1.f,-1.f), glm::vec2(2.f,2.f))); // screen coverage + + glLineWidth(2.0); glBegin(GL_LINES); glColor3f(0,0,1); @@ -1919,11 +1923,16 @@ void Application::renderVirtualOccluders() { AABox boxA(glm::vec3(0,0,0), 0.0125); boxA.scale(TREE_SCALE); VoxelProjectedShadow shadowA = _viewFrustum.getProjectedShadow(boxA); + AABox boxB(glm::vec3(0.0125,0,0.025), 0.0125); boxB.scale(TREE_SCALE); VoxelProjectedShadow shadowB = _viewFrustum.getProjectedShadow(boxB); + //CoverageMap::StorageResult result; + //result = map.storeInMap(&shadowB); // test this first since it's closer in Z-buffer + //result = map.storeInMap(&shadowA); + bool shadowAoccludesB = shadowA.occludes(shadowB); bool shadowBoccludesA = shadowB.occludes(shadowA); diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index cd6a4436ab..1c924a1a36 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -22,6 +22,7 @@ #include "Application.h" #include "Log.h" #include "VoxelConstants.h" +#include "CoverageMap.h" #include "InterfaceConfig.h" #include "renderer/ProgramObject.h" @@ -1159,9 +1160,10 @@ void VoxelSystem::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* dest struct FalseColorizeOccludedArgs { VoxelProjectedShadow occluder; ViewFrustum* viewFrustum; + CoverageMap* map; }; -bool VoxelSystem::falseColorizeOccludedOperation(VoxelNode* node, void* extraData) { +bool VoxelSystem::falseColorizeTestOccludedOperation(VoxelNode* node, void* extraData) { FalseColorizeOccludedArgs* args = (FalseColorizeOccludedArgs*) extraData; if (node->isColored()) { AABox voxelBox = node->getAABox(); @@ -1174,7 +1176,7 @@ bool VoxelSystem::falseColorizeOccludedOperation(VoxelNode* node, void* extraDat return true; // keep going! } -void VoxelSystem::falseColorizeOccluded() { +void VoxelSystem::falseColorizeTestOccluded() { FalseColorizeOccludedArgs args; args.viewFrustum = Application::getInstance()->getViewFrustum(); @@ -1182,7 +1184,36 @@ void VoxelSystem::falseColorizeOccluded() { box.scale(TREE_SCALE); args.occluder = args.viewFrustum->getProjectedShadow(box); - _tree->recurseTreeWithOperation(falseColorizeOccludedOperation,(void*)&args); + _tree->recurseTreeWithOperation(falseColorizeTestOccludedOperation,(void*)&args); + setupNewVoxelsForDrawing(); +} + +bool VoxelSystem::falseColorizeOccludedOperation(VoxelNode* node, void* extraData) { + FalseColorizeOccludedArgs* args = (FalseColorizeOccludedArgs*) extraData; + if (node->isColored() && node->isLeaf()) { + AABox voxelBox = node->getAABox(); + voxelBox.scale(TREE_SCALE); + VoxelProjectedShadow* voxelShadow = new VoxelProjectedShadow(args->viewFrustum->getProjectedShadow(voxelBox)); + CoverageMap::StorageResult result = args->map->storeInMap(voxelShadow); + if (result == CoverageMap::OCCLUDED) { + node->setFalseColor(255, 0, 0); + } + } + return true; // keep going! +} + +void VoxelSystem::falseColorizeOccluded() { + CoverageMap map(BoundingBox(glm::vec2(-1.f,-1.f), glm::vec2(2.f,2.f)), true); + FalseColorizeOccludedArgs args; + args.viewFrustum = Application::getInstance()->getViewFrustum(); + args.map = ↦ + + AABox box(glm::vec3(0.0125,0,0.025), 0.0125); + box.scale(TREE_SCALE); + args.occluder = args.viewFrustum->getProjectedShadow(box); + + _tree->recurseTreeWithOperationDistanceSorted(falseColorizeOccludedOperation, + args.viewFrustum->getPosition(), (void*)&args); setupNewVoxelsForDrawing(); } diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 6a07249454..f67960748a 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -57,6 +57,7 @@ public: void falseColorizeDistanceFromView(ViewFrustum* viewFrustum); void falseColorizeRandomEveryOther(); void falseColorizeOccluded(); + void falseColorizeTestOccluded(); void killLocalVoxels(); void setRenderPipelineWarnings(bool on) { _renderWarningsOn = on; }; @@ -122,6 +123,7 @@ private: static bool falseColorizeRandomEveryOtherOperation(VoxelNode* node, void* extraData); static bool collectStatsForTreesAndVBOsOperation(VoxelNode* node, void* extraData); static bool falseColorizeOccludedOperation(VoxelNode* node, void* extraData); + static bool falseColorizeTestOccludedOperation(VoxelNode* node, void* extraData); int updateNodeInArraysAsFullVBO(VoxelNode* node); int updateNodeInArraysAsPartialVBO(VoxelNode* node); diff --git a/libraries/voxels/src/CoverageMap.cpp b/libraries/voxels/src/CoverageMap.cpp index fa3d05101e..80b8776d8c 100644 --- a/libraries/voxels/src/CoverageMap.cpp +++ b/libraries/voxels/src/CoverageMap.cpp @@ -9,6 +9,11 @@ #include CoverageMap::~CoverageMap() { + if (_managePolygons) { + for (int i = 0; i < _polygonCount; i++) { + delete _polygons[i]; + } + } if (_polygons) { delete[] _polygons; } @@ -111,7 +116,7 @@ CoverageMap::StorageResult CoverageMap::storeInMap(VoxelProjectedShadow* polygon if (childMapBoundingBox.contains(polygon->getBoundingBox())) { // if no child map exists yet, then create it if (!_childMaps[i]) { - _childMaps[i] = new CoverageMap(childMapBoundingBox); + _childMaps[i] = new CoverageMap(childMapBoundingBox, _managePolygons); } return _childMaps[i]->storeInMap(polygon); } diff --git a/libraries/voxels/src/CoverageMap.h b/libraries/voxels/src/CoverageMap.h index 3f7dfe343d..c505b1e223 100644 --- a/libraries/voxels/src/CoverageMap.h +++ b/libraries/voxels/src/CoverageMap.h @@ -46,7 +46,8 @@ class CoverageMap { public: static const int NUMBER_OF_CHILDREN = 4; - CoverageMap(BoundingBox boundingBox) : _myBoundingBox(boundingBox) { init(); }; + CoverageMap(BoundingBox boundingBox, bool managePolygons = false) : + _myBoundingBox(boundingBox), _managePolygons(managePolygons) { init(); }; ~CoverageMap(); typedef enum {STORED, OCCLUDED, DOESNT_FIT} StorageResult; @@ -60,6 +61,7 @@ private: void storeInArray(VoxelProjectedShadow* polygon); BoundingBox _myBoundingBox; + bool _managePolygons; // will the coverage map delete the polygons on destruct int _polygonCount; // how many polygons at this level int _polygonArraySize; // how much room is there to store polygons at this level VoxelProjectedShadow** _polygons; diff --git a/libraries/voxels/src/VoxelProjectedShadow.cpp b/libraries/voxels/src/VoxelProjectedShadow.cpp index 2c138cdbec..0568c8b3c9 100644 --- a/libraries/voxels/src/VoxelProjectedShadow.cpp +++ b/libraries/voxels/src/VoxelProjectedShadow.cpp @@ -18,6 +18,7 @@ bool BoundingBox::contains(const BoundingBox& box) const { ); }; + void VoxelProjectedShadow::setVertex(int vertex, const glm::vec2& point) { _vertices[vertex] = point; @@ -92,4 +93,14 @@ bool VoxelProjectedShadow::pointInside(const glm::vec2& point) const { return ((intersections & 1) == 1); } +void VoxelProjectedShadow::printDebugDetails() const { + printf("VoxelProjectedShadow..."); + printf(" minX=%f maxX=%f minY=%f maxY=%f\n", getMinX(), getMaxX(), getMinY(), getMaxY()); + printf(" vertex count=%d \n", getVertexCount()); + for (int i = 0; i < getVertexCount(); i++) { + glm::vec2 point = getVertex(i); + printf(" vertex[%d] = %f, %f \n", i, point.x, point.y); + } +} + diff --git a/libraries/voxels/src/VoxelProjectedShadow.h b/libraries/voxels/src/VoxelProjectedShadow.h index 90af42d3bc..1d5e7cf022 100644 --- a/libraries/voxels/src/VoxelProjectedShadow.h +++ b/libraries/voxels/src/VoxelProjectedShadow.h @@ -25,7 +25,6 @@ public: class VoxelProjectedShadow { public: - VoxelProjectedShadow(int vertexCount = 0) : _vertexCount(vertexCount), _maxX(-FLT_MAX), _maxY(-FLT_MAX), _minX(FLT_MAX), _minY(FLT_MAX) { }; @@ -49,6 +48,8 @@ public: return BoundingBox(glm::vec2(_minX,_minY), glm::vec2(_maxX - _minX, _maxY - _minY)); }; + void printDebugDetails() const; + private: int _vertexCount; ShadowVertices _vertices; diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index b67e87597a..aea4a8778b 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -68,7 +68,48 @@ void VoxelTree::recurseNodeWithOperation(VoxelNode* node,RecurseVoxelTreeOperati } } -VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const { +// Recurses voxel tree calling the RecurseVoxelTreeOperation function for each node. +// stops recursion if operation function returns false. +void VoxelTree::recurseTreeWithOperationDistanceSorted(RecurseVoxelTreeOperation operation, + const glm::vec3& point, void* extraData) { + recurseNodeWithOperationDistanceSorted(rootNode, operation, point, extraData); +} + +// Recurses voxel node with an operation function +void VoxelTree::recurseNodeWithOperationDistanceSorted(VoxelNode* node, RecurseVoxelTreeOperation operation, + const glm::vec3& point, void* extraData) { + if (operation(node, extraData)) { + // determine the distance sorted order of our children + + VoxelNode* sortedChildren[NUMBER_OF_CHILDREN]; + float distancesToChildren[NUMBER_OF_CHILDREN]; + int indexOfChildren[NUMBER_OF_CHILDREN]; // not really needed + int currentCount = 0; + + for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { + VoxelNode* childNode = node->getChildAtIndex(i); + if (childNode) { + float distance = glm::distance(point, childNode->getCenter()); + currentCount = insertIntoSortedArrays((void*)childNode, distance, i, + (void**)&sortedChildren, (float*)&distancesToChildren, + (int*)&indexOfChildren, currentCount, NUMBER_OF_CHILDREN); + } + + + } + + for (int i = 0; i < currentCount; i++) { + VoxelNode* childNode = sortedChildren[i]; + if (childNode) { + recurseNodeWithOperationDistanceSorted(childNode, operation, point, extraData); + } + } + } +} + + +VoxelNode* VoxelTree::nodeForOctalCode(VoxelNode* ancestorNode, + unsigned char* needleCode, VoxelNode** parentOfFoundNode) const { // find the appropriate branch index based on this ancestorNode if (*needleCode > 0) { int branchForNeedle = branchIndexWithDescendant(ancestorNode->getOctalCode(), needleCode); diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index a238cb603a..ad644f8dc6 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -67,6 +67,8 @@ public: creationMode mode, bool destructive = false, bool debug = false); void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL); + void recurseTreeWithOperationDistanceSorted(RecurseVoxelTreeOperation operation, + const glm::vec3& point, void* extraData=NULL); int encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes, VoxelNodeBag& bag, const ViewFrustum* viewFrustum, @@ -117,6 +119,9 @@ private: static bool countVoxelsOperation(VoxelNode* node, void* extraData); void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData); + void recurseNodeWithOperationDistanceSorted(VoxelNode* node, RecurseVoxelTreeOperation operation, + const glm::vec3& point, void* extraData); + VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const; VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate); int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes,