From 91aea82418400e39192246c06a70ae454c5182a8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 12 Jun 2013 12:37:21 -0700 Subject: [PATCH] latest work on occlusion culling --- libraries/voxels/src/CoverageMap.cpp | 80 +++++++++++++++++-- libraries/voxels/src/CoverageMap.h | 13 ++- libraries/voxels/src/ViewFrustum.cpp | 3 + libraries/voxels/src/VoxelProjectedShadow.cpp | 12 ++- libraries/voxels/src/VoxelProjectedShadow.h | 10 ++- 5 files changed, 108 insertions(+), 10 deletions(-) diff --git a/libraries/voxels/src/CoverageMap.cpp b/libraries/voxels/src/CoverageMap.cpp index 80b8776d8c..35913a3777 100644 --- a/libraries/voxels/src/CoverageMap.cpp +++ b/libraries/voxels/src/CoverageMap.cpp @@ -6,7 +6,18 @@ // #include "CoverageMap.h" +#include #include +#include "Log.h" + +int CoverageMap::_mapCount = 0; + +CoverageMap::CoverageMap(BoundingBox boundingBox, bool isRoot, bool managePolygons) : + _isRoot(isRoot), _myBoundingBox(boundingBox), _managePolygons(managePolygons) { + _mapCount++; + init(); + printLog("CoverageMap created... _mapCount=%d\n",_mapCount); +}; CoverageMap::~CoverageMap() { if (_managePolygons) { @@ -54,24 +65,49 @@ BoundingBox CoverageMap::getChildBoundingBox(int childIndex) { void CoverageMap::growPolygonArray() { - VoxelProjectedShadow** newPolygons = new VoxelProjectedShadow*[_polygonArraySize + DEFAULT_GROW_SIZE]; + VoxelProjectedShadow** newPolygons = new VoxelProjectedShadow*[_polygonArraySize + DEFAULT_GROW_SIZE]; + float* newDistances = new float[_polygonArraySize + DEFAULT_GROW_SIZE]; + if (_polygons) { memcpy(newPolygons, _polygons, sizeof(VoxelProjectedShadow*) * _polygonCount); delete[] _polygons; + memcpy(newDistances, _polygonDistances, sizeof(float) * _polygonCount); + delete[] _polygonDistances; } _polygons = newPolygons; + _polygonDistances = newDistances; _polygonArraySize = _polygonArraySize + DEFAULT_GROW_SIZE; +printLog("CoverageMap::growPolygonArray() _polygonArraySize=%d...\n",_polygonArraySize); } +int CoverageMap::_maxPolygonsUsed = 0; + + // just handles storage in the array, doesn't test for occlusion or // determining if this is the correct map to store in! void CoverageMap::storeInArray(VoxelProjectedShadow* polygon) { + +//printLog("CoverageMap::storeInArray()..."); +//polygon->printDebugDetails(); + if (_polygonArraySize < _polygonCount + 1) { growPolygonArray(); } - _polygons[_polygonCount] = polygon; - _polygonCount++; + + // This old code assumes that polygons will always be added in z-buffer order, but that doesn't seem to + // be a good assumption. So instead, we will need to sort this by distance. Use a binary search to find the + // insertion point in this array, and shift the array accordingly + const int IGNORED = NULL; + _polygonCount = insertIntoSortedArrays((void*)polygon, polygon->getDistance(), IGNORED, + (void**)_polygons, _polygonDistances, IGNORED, + _polygonCount, _polygonArraySize); + + if (_polygonCount > _maxPolygonsUsed) { + _maxPolygonsUsed = _polygonCount; + printLog("CoverageMap new _maxPolygonsUsed reached=%d\n",_maxPolygonsUsed); + _myBoundingBox.printDebugDetails("map._myBoundingBox"); + } } @@ -100,11 +136,45 @@ void CoverageMap::storeInArray(VoxelProjectedShadow* polygon) { // end // return DOESNT_FIT CoverageMap::StorageResult CoverageMap::storeInMap(VoxelProjectedShadow* polygon) { - if (_myBoundingBox.contains(polygon->getBoundingBox())) { + +//printLog("CoverageMap::storeInMap()..."); +//polygon->printDebugDetails(); + + if (_isRoot || _myBoundingBox.contains(polygon->getBoundingBox())) { + +/* +if (_isRoot) { + printLog("CoverageMap::storeInMap()... this map _isRoot, so all polygons are contained....\n"); +} else { + printLog("CoverageMap::storeInMap()... _myBoundingBox.contains(polygon)....\n"); + _myBoundingBox.printDebugDetails("_myBoundingBox"); + polygon->getBoundingBox().printDebugDetails("polygon->getBoundingBox()"); +} +*/ + // check to make sure this polygon isn't occluded by something at this level for (int i = 0; i < _polygonCount; i++) { VoxelProjectedShadow* polygonAtThisLevel = _polygons[i]; + +//printLog("CoverageMap::storeInMap()... polygonAtThisLevel = _polygons[%d] =",i); +//polygonAtThisLevel->printDebugDetails(); + + // Check to make sure that the polygon in question is "behind" the polygon in the list + // otherwise, we don't need to test it's occlusion (although, it means we've potentially + // added an item previously that may be occluded??? Is that possible? Maybe not, because two + // voxels can't have the exact same outline. So one occludes the other, they can't both occlude + // each other. if (polygonAtThisLevel->occludes(*polygon)) { + +//printLog("CoverageMap::storeInMap()... polygonAtThisLevel->occludes(*polygon)...\n",i); + + // if the polygonAtThisLevel is actually behind the one we're inserting, then we don't + // want to report our inserted one as occluded, but we do want to add our inserted one. + if (polygonAtThisLevel->getDistance() >= polygon->getDistance()) { + storeInArray(polygon); + return STORED; + } + // this polygon is occluded by a closer polygon, so don't store it, and let the caller know return OCCLUDED; } } @@ -116,7 +186,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, _managePolygons); + _childMaps[i] = new CoverageMap(childMapBoundingBox, NOT_ROOT, _managePolygons); } return _childMaps[i]->storeInMap(polygon); } diff --git a/libraries/voxels/src/CoverageMap.h b/libraries/voxels/src/CoverageMap.h index c505b1e223..57db884593 100644 --- a/libraries/voxels/src/CoverageMap.h +++ b/libraries/voxels/src/CoverageMap.h @@ -41,13 +41,15 @@ // + class CoverageMap { public: static const int NUMBER_OF_CHILDREN = 4; + static const bool NOT_ROOT=false; + static const bool IS_ROOT=true; - CoverageMap(BoundingBox boundingBox, bool managePolygons = false) : - _myBoundingBox(boundingBox), _managePolygons(managePolygons) { init(); }; + CoverageMap(BoundingBox boundingBox, bool isRoot = IS_ROOT, bool managePolygons = false); ~CoverageMap(); typedef enum {STORED, OCCLUDED, DOESNT_FIT} StorageResult; @@ -60,14 +62,19 @@ private: void growPolygonArray(); void storeInArray(VoxelProjectedShadow* polygon); + bool _isRoot; // is this map the root, if so, it never returns DOESNT_FIT 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; + float* _polygonDistances; CoverageMap* _childMaps[NUMBER_OF_CHILDREN]; - static const int DEFAULT_GROW_SIZE = 500; + static const int DEFAULT_GROW_SIZE = 100; + static int _mapCount; + static int _maxPolygonsUsed; + }; diff --git a/libraries/voxels/src/ViewFrustum.cpp b/libraries/voxels/src/ViewFrustum.cpp index 6926a6190d..491a355040 100644 --- a/libraries/voxels/src/ViewFrustum.cpp +++ b/libraries/voxels/src/ViewFrustum.cpp @@ -513,5 +513,8 @@ VoxelProjectedShadow ViewFrustum::getProjectedShadow(const AABox& box) const { shadow.setVertex(i, projectedPoint); } } + // set the distance from our camera position, to the closest vertex + float distance = glm::distance(getPosition(), box.getCenter()); + shadow.setDistance(distance); return shadow; } diff --git a/libraries/voxels/src/VoxelProjectedShadow.cpp b/libraries/voxels/src/VoxelProjectedShadow.cpp index 0568c8b3c9..1ddb6370a9 100644 --- a/libraries/voxels/src/VoxelProjectedShadow.cpp +++ b/libraries/voxels/src/VoxelProjectedShadow.cpp @@ -7,6 +7,7 @@ #include "VoxelProjectedShadow.h" #include "GeometryUtil.h" +#include "Log.h" bool BoundingBox::contains(const BoundingBox& box) const { @@ -18,6 +19,15 @@ bool BoundingBox::contains(const BoundingBox& box) const { ); }; +void BoundingBox::printDebugDetails(const char* label) const { + if (label) { + printLog(label); + } else { + printLog("BoundingBox"); + } + printLog("\n corner=%f,%f size=%f,%f\n", corner.x, corner.y, size.x, size.y); +} + void VoxelProjectedShadow::setVertex(int vertex, const glm::vec2& point) { _vertices[vertex] = point; @@ -96,7 +106,7 @@ bool VoxelProjectedShadow::pointInside(const glm::vec2& point) const { 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()); + printf(" vertex count=%d distance=%f\n", getVertexCount(), getDistance()); 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 1d5e7cf022..ffe13bb9b6 100644 --- a/libraries/voxels/src/VoxelProjectedShadow.h +++ b/libraries/voxels/src/VoxelProjectedShadow.h @@ -20,13 +20,17 @@ public: glm::vec2 corner; glm::vec2 size; bool contains(const BoundingBox& box) const; + + void printDebugDetails(const char* label=NULL) const; }; class VoxelProjectedShadow { public: VoxelProjectedShadow(int vertexCount = 0) : - _vertexCount(vertexCount), _maxX(-FLT_MAX), _maxY(-FLT_MAX), _minX(FLT_MAX), _minY(FLT_MAX) + _vertexCount(vertexCount), + _maxX(-FLT_MAX), _maxY(-FLT_MAX), _minX(FLT_MAX), _minY(FLT_MAX), + _distance(0) { }; ~VoxelProjectedShadow() { }; @@ -36,6 +40,9 @@ public: int getVertexCount() const { return _vertexCount; }; void setVertexCount(int vertexCount) { _vertexCount = vertexCount; }; + float getDistance() const { return _distance; } + void setDistance(float distance) { _distance = distance; } + bool occludes(const VoxelProjectedShadow& occludee) const; bool pointInside(const glm::vec2& point) const; @@ -57,6 +64,7 @@ private: float _maxY; float _minX; float _minY; + float _distance; };