mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 18:44:00 +02:00
latest work on occlusion culling
This commit is contained in:
parent
627f61badb
commit
91aea82418
5 changed files with 108 additions and 10 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue