mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +02:00
Occlusion culling optimizations, added minimum polygon area, and only calculate projection matrix once
This commit is contained in:
parent
01ae437343
commit
6755dfd8e4
6 changed files with 69 additions and 19 deletions
|
@ -13,6 +13,35 @@
|
|||
int CoverageMap::_mapCount = 0;
|
||||
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.
|
||||
//
|
||||
// (0,0) (windowWidth, 0)
|
||||
// -1,1 1,1
|
||||
// +-----------------------+
|
||||
// | | |
|
||||
// | | |
|
||||
// | -1,0 | |
|
||||
// |-----------+-----------|
|
||||
// | 0,0 |
|
||||
// | | |
|
||||
// | | |
|
||||
// | | |
|
||||
// +-----------------------+
|
||||
// -1,-1 1,-1
|
||||
// (0,windowHeight) (windowWidth,windowHeight)
|
||||
//
|
||||
|
||||
// Choosing a minimum sized polygon. Since we know a typical window is approximately 1500 pixels wide
|
||||
// then a pixel on our screen will be ~ 2.0/1500 or 0.0013 "units" wide, similarly pixels are typically
|
||||
// about that tall as well. If we say that polygons should be at least 10x10 pixels to be considered "big enough"
|
||||
// then we can calculate a reasonable polygon area
|
||||
const int TYPICAL_SCREEN_WIDTH_IN_PIXELS = 1500;
|
||||
const int MINIMUM_POLYGON_AREA_SIDE_IN_PIXELS = 10;
|
||||
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) {
|
||||
_mapCount++;
|
||||
|
@ -51,9 +80,10 @@ void CoverageMap::erase() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/** Kee this debugging code for now....
|
||||
if (_isRoot) {
|
||||
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);
|
||||
|
@ -63,7 +93,6 @@ void CoverageMap::erase() {
|
|||
_mapCount = 0;
|
||||
}
|
||||
**/
|
||||
|
||||
}
|
||||
|
||||
void CoverageMap::init() {
|
||||
|
@ -143,6 +172,13 @@ void CoverageMap::storeInArray(VoxelProjectedPolygon* polygon) {
|
|||
|
||||
// possible results = STORED/NOT_STORED, OCCLUDED, DOESNT_FIT
|
||||
CoverageMap::StorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, bool storeIt) {
|
||||
|
||||
// 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.
|
||||
if (!polygon->getAllInView()) {
|
||||
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++) {
|
||||
|
@ -157,8 +193,13 @@ CoverageMap::StorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon,
|
|||
// want to report our inserted one as occluded, but we do want to add our inserted one.
|
||||
if (polygonAtThisLevel->getDistance() >= polygon->getDistance()) {
|
||||
if (storeIt) {
|
||||
storeInArray(polygon);
|
||||
return STORED;
|
||||
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;
|
||||
}
|
||||
|
@ -183,8 +224,13 @@ 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) {
|
||||
storeInArray(polygon);
|
||||
return STORED;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ public:
|
|||
static const bool NOT_ROOT=false;
|
||||
static const bool IS_ROOT=true;
|
||||
static const BoundingBox ROOT_BOUNDING_BOX;
|
||||
static const float MINIMUM_POLYGON_AREA_TO_STORE;
|
||||
|
||||
CoverageMap(BoundingBox boundingBox = ROOT_BOUNDING_BOX, bool isRoot = IS_ROOT, bool managePolygons = true);
|
||||
~CoverageMap();
|
||||
|
|
|
@ -115,6 +115,14 @@ void ViewFrustum::calculate() {
|
|||
_planes[NEAR_PLANE ].set3Points(_nearBottomRight,_nearBottomLeft,_nearTopLeft);
|
||||
_planes[FAR_PLANE ].set3Points(_farBottomLeft,_farBottomRight,_farTopRight);
|
||||
|
||||
// Also calculate our projection matrix in case people want to project points...
|
||||
// Projection matrix : Field of View, ratio, display range : near to far
|
||||
glm::mat4 projection = glm::perspective(_fieldOfView, _aspectRatio, _nearClip, _farClip);
|
||||
glm::vec3 lookAt = _position + _direction;
|
||||
glm::mat4 view = glm::lookAt(_position, lookAt, _up);
|
||||
|
||||
// Our ModelViewProjection : multiplication of our 3 matrices (note: model is identity, so we can drop it)
|
||||
_ourModelViewProjectionMatrix = projection * view; // Remember, matrix multiplication is the other way around
|
||||
}
|
||||
|
||||
//enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
|
||||
|
@ -425,18 +433,10 @@ void ViewFrustum::printDebugDetails() const {
|
|||
_eyeOffsetOrientation.w );
|
||||
}
|
||||
|
||||
|
||||
glm::vec2 ViewFrustum::projectPoint(glm::vec3 point, bool& pointInView) const {
|
||||
|
||||
// Projection matrix : Field of View, ratio, display range : near to far
|
||||
glm::mat4 projection = glm::perspective(_fieldOfView, _aspectRatio, _nearClip, _farClip);
|
||||
glm::vec3 lookAt = _position + _direction;
|
||||
glm::mat4 view = glm::lookAt(_position, lookAt, _up);
|
||||
// Our ModelViewProjection : multiplication of our 3 matrices (note: model is identity, so we can drop it)
|
||||
glm::mat4 VP = projection * view; // Remember, matrix multiplication is the other way around
|
||||
|
||||
glm::vec4 pointVec4 = glm::vec4(point,1);
|
||||
glm::vec4 projectedPointVec4 = VP * pointVec4;
|
||||
glm::vec4 pointVec4 = glm::vec4(point,1) ;
|
||||
glm::vec4 projectedPointVec4 = _ourModelViewProjectionMatrix * pointVec4;
|
||||
pointInView = (projectedPointVec4.w > 0); // math! If the w result is negative then the point is behind the viewer
|
||||
|
||||
// what happens with w is 0???
|
||||
|
|
|
@ -137,6 +137,8 @@ private:
|
|||
|
||||
const char* debugPlaneName (int plane) const;
|
||||
|
||||
// Used to project points
|
||||
glm::mat4 _ourModelViewProjectionMatrix;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ void VoxelProjectedPolygon::setVertex(int vertex, const glm::vec2& point) {
|
|||
|
||||
};
|
||||
|
||||
bool VoxelProjectedPolygon::occludes(const VoxelProjectedPolygon& occludee) const {
|
||||
bool VoxelProjectedPolygon::occludes(const VoxelProjectedPolygon& occludee, bool checkAllInView) const {
|
||||
|
||||
// if we are completely out of view, then we definitely don't occlude!
|
||||
// if the occludee is completely out of view, then we also don't occlude it
|
||||
|
@ -56,7 +56,7 @@ bool VoxelProjectedPolygon::occludes(const VoxelProjectedPolygon& occludee) cons
|
|||
// this is true, but unfortunately, we're not quite handling projects in the
|
||||
// case when SOME points are in view and others are not. So, we will not consider
|
||||
// occlusion for any shadows that are partially in view.
|
||||
if (!getAllInView() || !occludee.getAllInView() ) {
|
||||
if (checkAllInView && (!getAllInView() || !occludee.getAllInView())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ public:
|
|||
glm::vec2 corner;
|
||||
glm::vec2 size;
|
||||
bool contains(const BoundingBox& box) const;
|
||||
float area() const { return size.x * size.y; };
|
||||
|
||||
void printDebugDetails(const char* label=NULL) const;
|
||||
};
|
||||
|
@ -48,7 +49,7 @@ public:
|
|||
bool getAllInView() const { return _allInView; };
|
||||
void setAllInView(bool allInView) { _allInView = allInView; };
|
||||
|
||||
bool occludes(const VoxelProjectedPolygon& occludee) const;
|
||||
bool occludes(const VoxelProjectedPolygon& occludee, bool checkAllInView = false) const;
|
||||
bool pointInside(const glm::vec2& point) const;
|
||||
|
||||
float getMaxX() const { return _maxX; }
|
||||
|
|
Loading…
Reference in a new issue