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 <SharedUtil.h>
#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() {
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);
}

View file

@ -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;
};

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
};