latest work on occlusion culling

This commit is contained in:
ZappoMan 2013-06-12 12:37:21 -07:00
parent 627f61badb
commit 91aea82418
5 changed files with 108 additions and 10 deletions

View file

@ -6,7 +6,18 @@
// //
#include "CoverageMap.h" #include "CoverageMap.h"
#include <SharedUtil.h>
#include <string> #include <string>
#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() { CoverageMap::~CoverageMap() {
if (_managePolygons) { if (_managePolygons) {
@ -54,24 +65,49 @@ BoundingBox CoverageMap::getChildBoundingBox(int childIndex) {
void CoverageMap::growPolygonArray() { 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) { if (_polygons) {
memcpy(newPolygons, _polygons, sizeof(VoxelProjectedShadow*) * _polygonCount); memcpy(newPolygons, _polygons, sizeof(VoxelProjectedShadow*) * _polygonCount);
delete[] _polygons; delete[] _polygons;
memcpy(newDistances, _polygonDistances, sizeof(float) * _polygonCount);
delete[] _polygonDistances;
} }
_polygons = newPolygons; _polygons = newPolygons;
_polygonDistances = newDistances;
_polygonArraySize = _polygonArraySize + DEFAULT_GROW_SIZE; _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 // just handles storage in the array, doesn't test for occlusion or
// determining if this is the correct map to store in! // determining if this is the correct map to store in!
void CoverageMap::storeInArray(VoxelProjectedShadow* polygon) { void CoverageMap::storeInArray(VoxelProjectedShadow* polygon) {
//printLog("CoverageMap::storeInArray()...");
//polygon->printDebugDetails();
if (_polygonArraySize < _polygonCount + 1) { if (_polygonArraySize < _polygonCount + 1) {
growPolygonArray(); 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 // end
// return DOESNT_FIT // return DOESNT_FIT
CoverageMap::StorageResult CoverageMap::storeInMap(VoxelProjectedShadow* polygon) { 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 // check to make sure this polygon isn't occluded by something at this level
for (int i = 0; i < _polygonCount; i++) { for (int i = 0; i < _polygonCount; i++) {
VoxelProjectedShadow* polygonAtThisLevel = _polygons[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)) { 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; return OCCLUDED;
} }
} }
@ -116,7 +186,7 @@ CoverageMap::StorageResult CoverageMap::storeInMap(VoxelProjectedShadow* polygon
if (childMapBoundingBox.contains(polygon->getBoundingBox())) { if (childMapBoundingBox.contains(polygon->getBoundingBox())) {
// if no child map exists yet, then create it // if no child map exists yet, then create it
if (!_childMaps[i]) { if (!_childMaps[i]) {
_childMaps[i] = new CoverageMap(childMapBoundingBox, _managePolygons); _childMaps[i] = new CoverageMap(childMapBoundingBox, NOT_ROOT, _managePolygons);
} }
return _childMaps[i]->storeInMap(polygon); return _childMaps[i]->storeInMap(polygon);
} }

View file

@ -41,13 +41,15 @@
// //
class CoverageMap { class CoverageMap {
public: public:
static const int NUMBER_OF_CHILDREN = 4; 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) : CoverageMap(BoundingBox boundingBox, bool isRoot = IS_ROOT, bool managePolygons = false);
_myBoundingBox(boundingBox), _managePolygons(managePolygons) { init(); };
~CoverageMap(); ~CoverageMap();
typedef enum {STORED, OCCLUDED, DOESNT_FIT} StorageResult; typedef enum {STORED, OCCLUDED, DOESNT_FIT} StorageResult;
@ -60,14 +62,19 @@ private:
void growPolygonArray(); void growPolygonArray();
void storeInArray(VoxelProjectedShadow* polygon); void storeInArray(VoxelProjectedShadow* polygon);
bool _isRoot; // is this map the root, if so, it never returns DOESNT_FIT
BoundingBox _myBoundingBox; BoundingBox _myBoundingBox;
bool _managePolygons; // will the coverage map delete the polygons on destruct bool _managePolygons; // will the coverage map delete the polygons on destruct
int _polygonCount; // how many polygons at this level int _polygonCount; // how many polygons at this level
int _polygonArraySize; // how much room is there to store polygons at this level int _polygonArraySize; // how much room is there to store polygons at this level
VoxelProjectedShadow** _polygons; VoxelProjectedShadow** _polygons;
float* _polygonDistances;
CoverageMap* _childMaps[NUMBER_OF_CHILDREN]; 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;
}; };

View file

@ -513,5 +513,8 @@ VoxelProjectedShadow ViewFrustum::getProjectedShadow(const AABox& box) const {
shadow.setVertex(i, projectedPoint); 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; return shadow;
} }

View file

@ -7,6 +7,7 @@
#include "VoxelProjectedShadow.h" #include "VoxelProjectedShadow.h"
#include "GeometryUtil.h" #include "GeometryUtil.h"
#include "Log.h"
bool BoundingBox::contains(const BoundingBox& box) const { 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) { void VoxelProjectedShadow::setVertex(int vertex, const glm::vec2& point) {
_vertices[vertex] = point; _vertices[vertex] = point;
@ -96,7 +106,7 @@ bool VoxelProjectedShadow::pointInside(const glm::vec2& point) const {
void VoxelProjectedShadow::printDebugDetails() const { void VoxelProjectedShadow::printDebugDetails() const {
printf("VoxelProjectedShadow..."); printf("VoxelProjectedShadow...");
printf(" minX=%f maxX=%f minY=%f maxY=%f\n", getMinX(), getMaxX(), getMinY(), getMaxY()); 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++) { for (int i = 0; i < getVertexCount(); i++) {
glm::vec2 point = getVertex(i); glm::vec2 point = getVertex(i);
printf(" vertex[%d] = %f, %f \n", i, point.x, point.y); printf(" vertex[%d] = %f, %f \n", i, point.x, point.y);

View file

@ -20,13 +20,17 @@ public:
glm::vec2 corner; glm::vec2 corner;
glm::vec2 size; glm::vec2 size;
bool contains(const BoundingBox& box) const; bool contains(const BoundingBox& box) const;
void printDebugDetails(const char* label=NULL) const;
}; };
class VoxelProjectedShadow { class VoxelProjectedShadow {
public: public:
VoxelProjectedShadow(int vertexCount = 0) : 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() { }; ~VoxelProjectedShadow() { };
@ -36,6 +40,9 @@ public:
int getVertexCount() const { return _vertexCount; }; int getVertexCount() const { return _vertexCount; };
void setVertexCount(int vertexCount) { _vertexCount = 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 occludes(const VoxelProjectedShadow& occludee) const;
bool pointInside(const glm::vec2& point) const; bool pointInside(const glm::vec2& point) const;
@ -57,6 +64,7 @@ private:
float _maxY; float _maxY;
float _minX; float _minX;
float _minY; float _minY;
float _distance;
}; };