mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 06:53:01 +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 "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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue