mirror of
https://github.com/overte-org/overte.git
synced 2025-04-11 02:52:21 +02:00
implement partitioned CoverageRegions in CoverageMap to further optimize polygon compares
This commit is contained in:
parent
91f6d0fde5
commit
cadd596508
7 changed files with 338 additions and 136 deletions
|
@ -980,6 +980,7 @@ void Application::doFalseColorizeInView() {
|
|||
}
|
||||
|
||||
void Application::doFalseColorizeOccluded() {
|
||||
CoverageMap::wantDebugging = true;
|
||||
_voxels.falseColorizeOccluded();
|
||||
}
|
||||
|
||||
|
|
|
@ -1211,8 +1211,8 @@ bool VoxelSystem::falseColorizeOccludedOperation(VoxelNode* node, void* extraDat
|
|||
return true;
|
||||
}
|
||||
|
||||
CoverageMap::StorageResult result = args->map->checkMap(voxelPolygon, false);
|
||||
if (result == CoverageMap::OCCLUDED) {
|
||||
CoverageMapStorageResult result = args->map->checkMap(voxelPolygon, false);
|
||||
if (result == OCCLUDED) {
|
||||
args->nonLeavesOccluded++;
|
||||
delete voxelPolygon;
|
||||
|
||||
|
@ -1248,14 +1248,14 @@ bool VoxelSystem::falseColorizeOccludedOperation(VoxelNode* node, void* extraDat
|
|||
return true;
|
||||
}
|
||||
|
||||
CoverageMap::StorageResult result = args->map->checkMap(voxelPolygon, true);
|
||||
if (result == CoverageMap::OCCLUDED) {
|
||||
CoverageMapStorageResult result = args->map->checkMap(voxelPolygon, true);
|
||||
if (result == OCCLUDED) {
|
||||
node->setFalseColor(255, 0, 0);
|
||||
args->occludedVoxels++;
|
||||
} else if (result == CoverageMap::STORED) {
|
||||
} else if (result == STORED) {
|
||||
args->notOccludedVoxels++;
|
||||
//printLog("***** falseColorizeOccludedOperation() NODE is STORED *****\n");
|
||||
} else if (result == CoverageMap::DOESNT_FIT) {
|
||||
} else if (result == DOESNT_FIT) {
|
||||
//printLog("***** falseColorizeOccludedOperation() NODE DOESNT_FIT???? *****\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#include "Log.h"
|
||||
|
||||
int CoverageMap::_mapCount = 0;
|
||||
int CoverageMap::_checkMapRootCalls = 0;
|
||||
bool CoverageMap::wantDebugging = false;
|
||||
|
||||
const BoundingBox CoverageMap::ROOT_BOUNDING_BOX = BoundingBox(glm::vec2(-2.f,-2.f), glm::vec2(4.f,4.f));
|
||||
|
||||
// Coverage Map's polygon coordinates are from -1 to 1 in the following mapping to screen space.
|
||||
|
@ -42,9 +45,16 @@ const float TYPICAL_SCREEN_PIXEL_WIDTH = (2.0f / TYPICAL_SCREEN_WIDTH_IN_PIXELS)
|
|||
const float CoverageMap::MINIMUM_POLYGON_AREA_TO_STORE = (TYPICAL_SCREEN_PIXEL_WIDTH * MINIMUM_POLYGON_AREA_SIDE_IN_PIXELS) *
|
||||
(TYPICAL_SCREEN_PIXEL_WIDTH * MINIMUM_POLYGON_AREA_SIDE_IN_PIXELS);
|
||||
|
||||
|
||||
CoverageMap::CoverageMap(BoundingBox boundingBox, bool isRoot, bool managePolygons) :
|
||||
_isRoot(isRoot), _myBoundingBox(boundingBox), _managePolygons(managePolygons) {
|
||||
_isRoot(isRoot),
|
||||
_myBoundingBox(boundingBox),
|
||||
_managePolygons(managePolygons),
|
||||
_topHalf (boundingBox.topHalf() , false, managePolygons, TOP_HALF ),
|
||||
_bottomHalf (boundingBox.bottomHalf(), false, managePolygons, BOTTOM_HALF ),
|
||||
_leftHalf (boundingBox.leftHalf() , false, managePolygons, LEFT_HALF ),
|
||||
_rightHalf (boundingBox.rightHalf() , false, managePolygons, RIGHT_HALF ),
|
||||
_remainder (boundingBox, isRoot, managePolygons, REMAINDER )
|
||||
{
|
||||
_mapCount++;
|
||||
init();
|
||||
//printLog("CoverageMap created... _mapCount=%d\n",_mapCount);
|
||||
|
@ -55,25 +65,13 @@ CoverageMap::~CoverageMap() {
|
|||
};
|
||||
|
||||
void CoverageMap::erase() {
|
||||
// If we're in charge of managing the polygons, then clean them up first
|
||||
if (_managePolygons) {
|
||||
for (int i = 0; i < _polygonCount; i++) {
|
||||
delete _polygons[i];
|
||||
_polygons[i] = NULL; // do we need to do this?
|
||||
}
|
||||
}
|
||||
|
||||
// Now, clean up our local storage
|
||||
_polygonCount = 0;
|
||||
_polygonArraySize = 0;
|
||||
if (_polygons) {
|
||||
delete[] _polygons;
|
||||
_polygons = NULL;
|
||||
}
|
||||
if (_polygonDistances) {
|
||||
delete[] _polygonDistances;
|
||||
_polygonDistances = NULL;
|
||||
}
|
||||
// tell our regions to erase()
|
||||
_topHalf.erase();
|
||||
_bottomHalf.erase();
|
||||
_leftHalf.erase();
|
||||
_rightHalf.erase();
|
||||
_remainder.erase();
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
if (_childMaps[i]) {
|
||||
delete _childMaps[i];
|
||||
|
@ -81,26 +79,25 @@ void CoverageMap::erase() {
|
|||
}
|
||||
}
|
||||
|
||||
/** Kee this debugging code for now....
|
||||
if (_isRoot) {
|
||||
if (_isRoot && wantDebugging) {
|
||||
printLog("CoverageMap last to be deleted...\n");
|
||||
printLog("MINIMUM_POLYGON_AREA_TO_STORE=%f\n",MINIMUM_POLYGON_AREA_TO_STORE);
|
||||
printLog("_mapCount=%d\n",_mapCount);
|
||||
printLog("_maxPolygonsUsed=%d\n",_maxPolygonsUsed);
|
||||
printLog("_totalPolygons=%d\n",_totalPolygons);
|
||||
|
||||
_maxPolygonsUsed = 0;
|
||||
_totalPolygons = 0;
|
||||
printLog("_checkMapRootCalls=%d\n",_checkMapRootCalls);
|
||||
printLog("_maxPolygonsUsed=%d\n",CoverageRegion::_maxPolygonsUsed);
|
||||
printLog("_totalPolygons=%d\n",CoverageRegion::_totalPolygons);
|
||||
printLog("_occlusionTests=%d\n",CoverageRegion::_occlusionTests);
|
||||
printLog("_outOfOrderPolygon=%d\n",CoverageRegion::_outOfOrderPolygon);
|
||||
CoverageRegion::_maxPolygonsUsed = 0;
|
||||
CoverageRegion::_totalPolygons = 0;
|
||||
CoverageRegion::_occlusionTests = 0;
|
||||
CoverageRegion::_outOfOrderPolygon = 0;
|
||||
_mapCount = 0;
|
||||
_checkMapRootCalls = 0;
|
||||
}
|
||||
**/
|
||||
}
|
||||
|
||||
void CoverageMap::init() {
|
||||
_polygonCount = 0;
|
||||
_polygonArraySize = 0;
|
||||
_polygons = NULL;
|
||||
_polygonDistances = NULL;
|
||||
memset(_childMaps,0,sizeof(_childMaps));
|
||||
}
|
||||
|
||||
|
@ -124,55 +121,12 @@ BoundingBox CoverageMap::getChildBoundingBox(int childIndex) {
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
void CoverageMap::growPolygonArray() {
|
||||
VoxelProjectedPolygon** newPolygons = new VoxelProjectedPolygon*[_polygonArraySize + DEFAULT_GROW_SIZE];
|
||||
float* newDistances = new float[_polygonArraySize + DEFAULT_GROW_SIZE];
|
||||
|
||||
|
||||
if (_polygons) {
|
||||
memcpy(newPolygons, _polygons, sizeof(VoxelProjectedPolygon*) * _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;
|
||||
int CoverageMap::_totalPolygons = 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(VoxelProjectedPolygon* polygon) {
|
||||
|
||||
_totalPolygons++;
|
||||
|
||||
if (_polygonArraySize < _polygonCount + 1) {
|
||||
growPolygonArray();
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// possible results = STORED/NOT_STORED, OCCLUDED, DOESNT_FIT
|
||||
CoverageMap::StorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, bool storeIt) {
|
||||
CoverageMapStorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, bool storeIt) {
|
||||
|
||||
if (_isRoot) {
|
||||
_checkMapRootCalls++;
|
||||
}
|
||||
|
||||
// short circuit: we don't handle polygons that aren't all in view, so, if the polygon in question is
|
||||
// not in view, then we just discard it with a DOESNT_FIT, this saves us time checking values later.
|
||||
|
@ -180,35 +134,46 @@ CoverageMap::StorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon,
|
|||
return DOESNT_FIT;
|
||||
}
|
||||
|
||||
if (_isRoot || _myBoundingBox.contains(polygon->getBoundingBox())) {
|
||||
// check to make sure this polygon isn't occluded by something at this level
|
||||
for (int i = 0; i < _polygonCount; i++) {
|
||||
VoxelProjectedPolygon* polygonAtThisLevel = _polygons[i];
|
||||
// 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 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()) {
|
||||
if (storeIt) {
|
||||
if (polygon->getBoundingBox().area() > MINIMUM_POLYGON_AREA_TO_STORE) {
|
||||
//printLog("storing polygon of area: %f\n",polygon->getBoundingBox().area());
|
||||
storeInArray(polygon);
|
||||
return STORED;
|
||||
} else {
|
||||
return NOT_STORED;
|
||||
}
|
||||
} else {
|
||||
return NOT_STORED;
|
||||
}
|
||||
}
|
||||
// this polygon is occluded by a closer polygon, so don't store it, and let the caller know
|
||||
return OCCLUDED;
|
||||
}
|
||||
BoundingBox polygonBox(polygon->getBoundingBox());
|
||||
if (_isRoot || _myBoundingBox.contains(polygonBox)) {
|
||||
|
||||
CoverageMapStorageResult result = NOT_STORED;
|
||||
CoverageRegion* storeIn = &_remainder;
|
||||
bool fitsInAHalf = false;
|
||||
|
||||
// Check each half of the box independently
|
||||
if (_topHalf.contains(polygonBox)) {
|
||||
result = _topHalf.checkRegion(polygon, polygonBox, storeIt);
|
||||
storeIn = &_topHalf;
|
||||
fitsInAHalf = true;
|
||||
} else if (_bottomHalf.contains(polygonBox)) {
|
||||
result = _bottomHalf.checkRegion(polygon, polygonBox, storeIt);
|
||||
storeIn = &_bottomHalf;
|
||||
fitsInAHalf = true;
|
||||
} else if (_leftHalf.contains(polygonBox)) {
|
||||
result = _leftHalf.checkRegion(polygon, polygonBox, storeIt);
|
||||
storeIn = &_leftHalf;
|
||||
fitsInAHalf = true;
|
||||
} else if (_rightHalf.contains(polygonBox)) {
|
||||
result = _rightHalf.checkRegion(polygon, polygonBox, storeIt);
|
||||
storeIn = &_rightHalf;
|
||||
fitsInAHalf = true;
|
||||
}
|
||||
|
||||
// if we got this far, there are one of two possibilities, either a polygon doesn't fit
|
||||
// in one of the halves, or it did fit, but it wasn't occluded by anything only in that
|
||||
// half. In either of these cases, we want to check our remainder region to see if its
|
||||
// occluded by anything there
|
||||
if (!(result == STORED || result == OCCLUDED)) {
|
||||
result = _remainder.checkRegion(polygon, polygonBox, storeIt);
|
||||
}
|
||||
|
||||
// It's possible that this first set of checks might have resulted in an out of order polygon
|
||||
// in which case we just return..
|
||||
if (result == STORED || result == OCCLUDED) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// if we made it here, then it means the polygon being stored is not occluded
|
||||
// at this level of the quad tree, so we can continue to insert it into the map.
|
||||
// First we check to see if it fits in any of our sub maps
|
||||
|
@ -225,9 +190,9 @@ CoverageMap::StorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon,
|
|||
// if we got this far, then the polygon is in our bounding box, but doesn't fit in
|
||||
// any of our child bounding boxes, so we should add it here.
|
||||
if (storeIt) {
|
||||
if (polygon->getBoundingBox().area() > MINIMUM_POLYGON_AREA_TO_STORE) {
|
||||
if (polygon->getBoundingBox().area() > CoverageMap::MINIMUM_POLYGON_AREA_TO_STORE) {
|
||||
//printLog("storing polygon of area: %f\n",polygon->getBoundingBox().area());
|
||||
storeInArray(polygon);
|
||||
storeIn->storeInArray(polygon);
|
||||
return STORED;
|
||||
} else {
|
||||
return NOT_STORED;
|
||||
|
@ -238,3 +203,171 @@ CoverageMap::StorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon,
|
|||
}
|
||||
return DOESNT_FIT;
|
||||
}
|
||||
|
||||
|
||||
CoverageRegion::CoverageRegion(BoundingBox boundingBox, bool isRoot, bool managePolygons, RegionName regionName) :
|
||||
_isRoot(isRoot),
|
||||
_myBoundingBox(boundingBox),
|
||||
_managePolygons(managePolygons),
|
||||
_regionName(regionName)
|
||||
{
|
||||
init();
|
||||
};
|
||||
|
||||
CoverageRegion::~CoverageRegion() {
|
||||
erase();
|
||||
};
|
||||
|
||||
void CoverageRegion::init() {
|
||||
_polygonCount = 0;
|
||||
_polygonArraySize = 0;
|
||||
_polygons = NULL;
|
||||
_polygonDistances = NULL;
|
||||
}
|
||||
|
||||
|
||||
void CoverageRegion::erase() {
|
||||
|
||||
/*
|
||||
if (_polygonCount) {
|
||||
printLog("CoverageRegion::erase()...\n");
|
||||
printLog("_polygonCount=%d\n",_polygonCount);
|
||||
_myBoundingBox.printDebugDetails(getRegionName());
|
||||
//for (int i = 0; i < _polygonCount; i++) {
|
||||
// printLog("_polygons[%d]=",i);
|
||||
// _polygons[i]->getBoundingBox().printDebugDetails();
|
||||
//}
|
||||
}
|
||||
*/
|
||||
// If we're in charge of managing the polygons, then clean them up first
|
||||
if (_managePolygons) {
|
||||
for (int i = 0; i < _polygonCount; i++) {
|
||||
delete _polygons[i];
|
||||
_polygons[i] = NULL; // do we need to do this?
|
||||
}
|
||||
}
|
||||
|
||||
// Now, clean up our local storage
|
||||
_polygonCount = 0;
|
||||
_polygonArraySize = 0;
|
||||
if (_polygons) {
|
||||
delete[] _polygons;
|
||||
_polygons = NULL;
|
||||
}
|
||||
if (_polygonDistances) {
|
||||
delete[] _polygonDistances;
|
||||
_polygonDistances = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CoverageRegion::growPolygonArray() {
|
||||
VoxelProjectedPolygon** newPolygons = new VoxelProjectedPolygon*[_polygonArraySize + DEFAULT_GROW_SIZE];
|
||||
float* newDistances = new float[_polygonArraySize + DEFAULT_GROW_SIZE];
|
||||
|
||||
|
||||
if (_polygons) {
|
||||
memcpy(newPolygons, _polygons, sizeof(VoxelProjectedPolygon*) * _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);
|
||||
}
|
||||
|
||||
const char* CoverageRegion::getRegionName() const {
|
||||
switch (_regionName) {
|
||||
case TOP_HALF:
|
||||
return "TOP_HALF";
|
||||
case BOTTOM_HALF:
|
||||
return "BOTTOM_HALF";
|
||||
case LEFT_HALF:
|
||||
return "LEFT_HALF";
|
||||
case RIGHT_HALF:
|
||||
return "RIGHT_HALF";
|
||||
default:
|
||||
case REMAINDER:
|
||||
return "REMAINDER";
|
||||
}
|
||||
return "REMAINDER";
|
||||
}
|
||||
|
||||
int CoverageRegion::_maxPolygonsUsed = 0;
|
||||
int CoverageRegion::_totalPolygons = 0;
|
||||
int CoverageRegion::_occlusionTests = 0;
|
||||
int CoverageRegion::_outOfOrderPolygon = 0;
|
||||
|
||||
// just handles storage in the array, doesn't test for occlusion or
|
||||
// determining if this is the correct map to store in!
|
||||
void CoverageRegion::storeInArray(VoxelProjectedPolygon* polygon) {
|
||||
|
||||
_totalPolygons++;
|
||||
|
||||
if (_polygonArraySize < _polygonCount + 1) {
|
||||
growPolygonArray();
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// Debugging and Optimization Tuning code.
|
||||
if (_polygonCount > _maxPolygonsUsed) {
|
||||
_maxPolygonsUsed = _polygonCount;
|
||||
//printLog("CoverageRegion new _maxPolygonsUsed reached=%d region=%s\n",_maxPolygonsUsed, getRegionName());
|
||||
//_myBoundingBox.printDebugDetails("map._myBoundingBox");
|
||||
} else {
|
||||
//printLog("CoverageRegion::storeInArray() _polygonCount=%d region=%s\n",_polygonCount, getRegionName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
CoverageMapStorageResult CoverageRegion::checkRegion(VoxelProjectedPolygon* polygon, const BoundingBox& polygonBox, bool storeIt) {
|
||||
|
||||
CoverageMapStorageResult result = DOESNT_FIT;
|
||||
|
||||
if (_isRoot || _myBoundingBox.contains(polygonBox)) {
|
||||
result = NOT_STORED; // if we got here, then we DO fit...
|
||||
|
||||
// check to make sure this polygon isn't occluded by something at this level
|
||||
for (int i = 0; i < _polygonCount; i++) {
|
||||
VoxelProjectedPolygon* polygonAtThisLevel = _polygons[i];
|
||||
// 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.
|
||||
|
||||
|
||||
_occlusionTests++;
|
||||
if (polygonAtThisLevel->occludes(*polygon)) {
|
||||
// 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()) {
|
||||
_outOfOrderPolygon++;
|
||||
if (storeIt) {
|
||||
if (polygon->getBoundingBox().area() > CoverageMap::MINIMUM_POLYGON_AREA_TO_STORE) {
|
||||
//printLog("storing polygon of area: %f\n",polygon->getBoundingBox().area());
|
||||
storeInArray(polygon);
|
||||
return STORED;
|
||||
} else {
|
||||
return NOT_STORED;
|
||||
}
|
||||
} else {
|
||||
return NOT_STORED;
|
||||
}
|
||||
}
|
||||
// this polygon is occluded by a closer polygon, so don't store it, and let the caller know
|
||||
return OCCLUDED;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,45 @@
|
|||
#include <glm/glm.hpp>
|
||||
#include "VoxelProjectedPolygon.h"
|
||||
|
||||
typedef enum {STORED, OCCLUDED, DOESNT_FIT, NOT_STORED} CoverageMapStorageResult;
|
||||
typedef enum {TOP_HALF, BOTTOM_HALF, LEFT_HALF, RIGHT_HALF, REMAINDER} RegionName;
|
||||
|
||||
class CoverageRegion {
|
||||
|
||||
public:
|
||||
|
||||
CoverageRegion(BoundingBox boundingBox, bool isRoot, bool managePolygons = true, RegionName regionName = REMAINDER);
|
||||
~CoverageRegion();
|
||||
|
||||
CoverageMapStorageResult checkRegion(VoxelProjectedPolygon* polygon, const BoundingBox& polygonBox, bool storeIt);
|
||||
void storeInArray(VoxelProjectedPolygon* polygon);
|
||||
|
||||
bool contains(const BoundingBox& box) const { return _myBoundingBox.contains(box); };
|
||||
void erase(); // erase the coverage region
|
||||
|
||||
static int _maxPolygonsUsed;
|
||||
static int _totalPolygons;
|
||||
static int _occlusionTests;
|
||||
static int _outOfOrderPolygon;
|
||||
|
||||
|
||||
const char* getRegionName() const;
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
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
|
||||
RegionName _regionName;
|
||||
int _polygonCount; // how many polygons at this level
|
||||
int _polygonArraySize; // how much room is there to store polygons at this level
|
||||
VoxelProjectedPolygon** _polygons;
|
||||
float* _polygonDistances;
|
||||
void growPolygonArray();
|
||||
static const int DEFAULT_GROW_SIZE = 100;
|
||||
};
|
||||
|
||||
class CoverageMap {
|
||||
|
||||
public:
|
||||
|
@ -24,32 +63,32 @@ public:
|
|||
CoverageMap(BoundingBox boundingBox = ROOT_BOUNDING_BOX, bool isRoot = IS_ROOT, bool managePolygons = true);
|
||||
~CoverageMap();
|
||||
|
||||
typedef enum {STORED, OCCLUDED, DOESNT_FIT, NOT_STORED} StorageResult;
|
||||
StorageResult checkMap(VoxelProjectedPolygon* polygon, bool storeIt = true);
|
||||
CoverageMapStorageResult checkMap(VoxelProjectedPolygon* polygon, bool storeIt = true);
|
||||
|
||||
BoundingBox getChildBoundingBox(int childIndex);
|
||||
|
||||
void erase(); // erase the coverage map
|
||||
|
||||
static bool wantDebugging;
|
||||
|
||||
private:
|
||||
void init();
|
||||
void growPolygonArray();
|
||||
void storeInArray(VoxelProjectedPolygon* 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
|
||||
VoxelProjectedPolygon** _polygons;
|
||||
float* _polygonDistances;
|
||||
CoverageMap* _childMaps[NUMBER_OF_CHILDREN];
|
||||
bool _managePolygons; // will the coverage map delete the polygons on destruct
|
||||
|
||||
// We divide the map into 5 regions representing each possible half of the map, and the whole map
|
||||
// this allows us to keep the list of polygons shorter
|
||||
CoverageRegion _topHalf;
|
||||
CoverageRegion _bottomHalf;
|
||||
CoverageRegion _leftHalf;
|
||||
CoverageRegion _rightHalf;
|
||||
CoverageRegion _remainder;
|
||||
|
||||
static const int DEFAULT_GROW_SIZE = 100;
|
||||
static int _mapCount;
|
||||
static int _maxPolygonsUsed;
|
||||
static int _totalPolygons;
|
||||
|
||||
static int _mapCount;
|
||||
static int _checkMapRootCalls;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -10,6 +10,30 @@
|
|||
#include "Log.h"
|
||||
|
||||
|
||||
BoundingBox BoundingBox::topHalf() const {
|
||||
float halfY = size.y/2.0f;
|
||||
BoundingBox result(glm::vec2(corner.x,corner.y + halfY), glm::vec2(size.x, halfY));
|
||||
return result;
|
||||
}
|
||||
|
||||
BoundingBox BoundingBox::bottomHalf() const {
|
||||
float halfY = size.y/2.0f;
|
||||
BoundingBox result(corner, glm::vec2(size.x, halfY));
|
||||
return result;
|
||||
}
|
||||
|
||||
BoundingBox BoundingBox::leftHalf() const {
|
||||
float halfX = size.x/2.0f;
|
||||
BoundingBox result(corner, glm::vec2(halfX, size.y));
|
||||
return result;
|
||||
}
|
||||
|
||||
BoundingBox BoundingBox::rightHalf() const {
|
||||
float halfX = size.x/2.0f;
|
||||
BoundingBox result(glm::vec2(corner.x + halfX , corner.y), glm::vec2(halfX, size.y));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BoundingBox::contains(const BoundingBox& box) const {
|
||||
return (
|
||||
(box.corner.x >= corner.x) &&
|
||||
|
|
|
@ -21,6 +21,11 @@ public:
|
|||
glm::vec2 size;
|
||||
bool contains(const BoundingBox& box) const;
|
||||
float area() const { return size.x * size.y; };
|
||||
|
||||
BoundingBox topHalf() const;
|
||||
BoundingBox bottomHalf() const;
|
||||
BoundingBox leftHalf() const;
|
||||
BoundingBox rightHalf() const;
|
||||
|
||||
void printDebugDetails(const char* label=NULL) const;
|
||||
};
|
||||
|
|
|
@ -1132,9 +1132,9 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
|||
if (voxelPolygon->getAllInView()) {
|
||||
//node->printDebugDetails("upper section, voxelPolygon->getAllInView() node=");
|
||||
|
||||
CoverageMap::StorageResult result = params.map->checkMap(voxelPolygon, false);
|
||||
CoverageMapStorageResult result = params.map->checkMap(voxelPolygon, false);
|
||||
delete voxelPolygon; // cleanup
|
||||
if (result == CoverageMap::OCCLUDED) {
|
||||
if (result == OCCLUDED) {
|
||||
//node->printDebugDetails("upper section, non-Leaf is occluded!! node=");
|
||||
//args->nonLeavesOccluded++;
|
||||
|
||||
|
@ -1247,17 +1247,17 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
|||
// In order to check occlusion culling, the shadow has to be "all in view" otherwise, we will ignore occlusion
|
||||
// culling and proceed as normal
|
||||
if (voxelPolygon->getAllInView()) {
|
||||
CoverageMap::StorageResult result = params.map->checkMap(voxelPolygon, true);
|
||||
CoverageMapStorageResult result = params.map->checkMap(voxelPolygon, true);
|
||||
|
||||
// In all cases where the shadow wasn't stored, we need to free our own memory.
|
||||
// In the case where it is stored, the CoverageMap will free memory for us later.
|
||||
if (result != CoverageMap::STORED) {
|
||||
if (result != STORED) {
|
||||
delete voxelPolygon;
|
||||
}
|
||||
|
||||
// If while attempting to add this voxel's shadow, we determined it was occluded, then
|
||||
// we don't need to process it further and we can exit early.
|
||||
if (result == CoverageMap::OCCLUDED) {
|
||||
if (result == OCCLUDED) {
|
||||
childIsOccluded = true;
|
||||
}
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue