mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 15:23:56 +02:00
Implementing the octree selection from frustum
This commit is contained in:
parent
1b5499b3d6
commit
18d8a2fb42
4 changed files with 150 additions and 6 deletions
|
@ -125,6 +125,9 @@ public:
|
|||
float calculateRenderAccuracy(const AABox& bounds, float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
|
||||
int boundaryLevelAdjust = 0) const;
|
||||
|
||||
enum PlaneIndex { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE, NUM_PLANES };
|
||||
|
||||
const ::Plane* getPlanes() const { return _planes; }
|
||||
private:
|
||||
// Used for keyhole calculations
|
||||
ViewFrustum::location pointInKeyhole(const glm::vec3& point) const;
|
||||
|
@ -160,7 +163,7 @@ private:
|
|||
float _fieldOfView = DEFAULT_FIELD_OF_VIEW_DEGREES;
|
||||
glm::vec4 _corners[8];
|
||||
glm::vec3 _cornersWorld[8];
|
||||
enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
|
||||
// enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
|
||||
::Plane _planes[6]; // How will this be used?
|
||||
|
||||
const char* debugPlaneName (int plane) const;
|
||||
|
|
|
@ -80,6 +80,11 @@ void DrawSceneOctree::run(const SceneContextPointer& sceneContext,
|
|||
return;
|
||||
}
|
||||
|
||||
// Try that:
|
||||
render::ItemIDs items;
|
||||
scene->getSpatialTree().select(items, *args->_viewFrustum);
|
||||
|
||||
|
||||
// Allright, something to render let's do it
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
glm::mat4 projMat;
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
//
|
||||
#include "Octree.h"
|
||||
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
|
||||
using namespace render;
|
||||
|
||||
|
@ -68,7 +70,7 @@ Octree::Location Octree::Location::evalFromRange(const Coord3& minCoord, const C
|
|||
}
|
||||
|
||||
Octree::Indices Octree::indexConcreteCellPath(const Locations& path) const {
|
||||
Index currentIndex = ROOT;
|
||||
Index currentIndex = ROOT_CELL;
|
||||
Indices cellPath(1, currentIndex);
|
||||
|
||||
for (int l = 1; l < path.size(); l++) {
|
||||
|
@ -217,3 +219,114 @@ ItemSpatialTree::Index ItemSpatialTree::resetItem(Index oldCell, const Location&
|
|||
}
|
||||
}
|
||||
|
||||
int ItemSpatialTree::select(ItemIDs& selection, const ViewFrustum& frustum) const {
|
||||
auto worldPlanes = frustum.getPlanes();
|
||||
Coord4f planes[6];
|
||||
for (int i = 0; i < ViewFrustum::NUM_PLANES; i++) {
|
||||
::Plane octPlane;
|
||||
octPlane.setNormalAndPoint(worldPlanes[i].getNormal(), evalCoordf(worldPlanes[i].getPoint(), ROOT_DEPTH));
|
||||
planes[i] = Coord4f(octPlane.getNormal(), octPlane.getDCoefficient());
|
||||
}
|
||||
return Octree::select(selection, planes);
|
||||
}
|
||||
|
||||
int Octree::select(ItemIDs& selection, const glm::vec4 frustum[6]) const {
|
||||
|
||||
Index cellID = ROOT_CELL;
|
||||
selectTraverse(cellID, selection, frustum);
|
||||
return selection.size();
|
||||
}
|
||||
|
||||
int Octree::selectTraverse(Index cellID, ItemIDs& selection, const Coord4f frustum[6]) const {
|
||||
int numItemsIn = selection.size();
|
||||
auto cell = getConcreteCell(cellID);
|
||||
|
||||
auto intersection = Octree::Location::intersectCell(cell.getlocation(), frustum);
|
||||
switch (intersection) {
|
||||
case Octree::Location::Outside:
|
||||
// cell is outside, stop traversing this branch
|
||||
return 0;
|
||||
break;
|
||||
case Octree::Location::Inside: {
|
||||
// traverse all the Cell Branch and collect items in the selection
|
||||
selection.push_back(cellID);
|
||||
break;
|
||||
}
|
||||
case Octree::Location::Intersect:
|
||||
default: {
|
||||
// Cell is partially in
|
||||
selection.push_back(cellID);
|
||||
|
||||
// Collect the items of this cell
|
||||
|
||||
// then traverse further
|
||||
for (int i = 0; i < NUM_OCTANTS; i++) {
|
||||
Index subCellID = cell.child((Link)i);
|
||||
if (subCellID != INVALID) {
|
||||
selectTraverse(subCellID, selection, frustum);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return selection.size() - numItemsIn;
|
||||
}
|
||||
|
||||
|
||||
Octree::Location::Intersection Octree::Location::intersectCell(const Location& cell, const Coord4f frustum[6]) {
|
||||
const Coord3f CornerOffsets[8] = {
|
||||
{ 0.0, 0.0, 0.0 },
|
||||
{ 1.0, 0.0, 0.0 },
|
||||
{ 0.0, 1.0, 0.0 },
|
||||
{ 1.0, 1.0, 0.0 },
|
||||
{ 0.0, 0.0, 1.0 },
|
||||
{ 1.0, 0.0, 1.0 },
|
||||
{ 0.0, 1.0, 1.0 },
|
||||
{ 1.0, 1.0, 1.0 },
|
||||
};
|
||||
|
||||
struct Tool {
|
||||
static int normalToIndex(const Coord3f& n) {
|
||||
int index = 0;
|
||||
if (n.x >= 0.0) index |= 1;
|
||||
if (n.y >= 0.0) index |= 2;
|
||||
if (n.z >= 0.0) index |= 4;
|
||||
return index;
|
||||
}
|
||||
|
||||
static bool halfPlaneTest(const Coord4f& plane, const Coord3f& pos) {
|
||||
return (glm::dot(plane, Coord4f(pos, 1.0f)) >= 0.0f);
|
||||
}
|
||||
};
|
||||
|
||||
Coord3f cellSize = Coord3f(Octree::getInvDepthDimension(cell.depth));
|
||||
Coord3f cellPos = Coord3f(cell.pos) * cellSize;
|
||||
|
||||
bool partialFlag = false;
|
||||
for (int p = 0; p < ViewFrustum::NUM_PLANES; p++) {
|
||||
Coord4f plane = frustum[p];
|
||||
Coord3f planeNormal(plane);
|
||||
|
||||
int index = Tool::normalToIndex(planeNormal);
|
||||
|
||||
auto negTestPoint = cellPos + cellSize * CornerOffsets[index];
|
||||
|
||||
if (!Tool::halfPlaneTest(plane, negTestPoint)) {
|
||||
return Outside;
|
||||
}
|
||||
|
||||
index = Tool::normalToIndex(-planeNormal);
|
||||
|
||||
auto posTestPoint = cellPos + cellSize * CornerOffsets[index];
|
||||
|
||||
if (!Tool::halfPlaneTest(plane, posTestPoint)) {
|
||||
partialFlag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (partialFlag) {
|
||||
return Intersect;
|
||||
}
|
||||
|
||||
return Inside;
|
||||
}
|
|
@ -85,6 +85,7 @@ namespace render {
|
|||
|
||||
// Max depth is 15 => 32Km root down to 1m cells
|
||||
using Depth = int8_t;
|
||||
static const Depth ROOT_DEPTH{ 0 };
|
||||
static const Depth MAX_DEPTH { 15 };
|
||||
static const double INV_DEPTH_DIM[Octree::MAX_DEPTH + 1];
|
||||
|
||||
|
@ -95,6 +96,8 @@ namespace render {
|
|||
using Coord = int16_t;
|
||||
using Coord3 = glm::i16vec3;
|
||||
using Coord4 = glm::i16vec4;
|
||||
using Coord3f = glm::vec3;
|
||||
using Coord4f = glm::vec4;
|
||||
|
||||
static Coord depthBitmask(Depth depth) { return Coord(1 << (MAX_DEPTH - depth)); }
|
||||
|
||||
|
@ -122,7 +125,7 @@ namespace render {
|
|||
|
||||
Coord3 pos{ 0 };
|
||||
uint8_t spare{ 0 };
|
||||
Depth depth{ 0 };
|
||||
Depth depth{ ROOT_DEPTH };
|
||||
|
||||
bool operator== (const Location& right) const { return pos == right.pos && depth == right.depth; }
|
||||
|
||||
|
@ -140,13 +143,22 @@ namespace render {
|
|||
|
||||
// Eval the location best fitting the specified range
|
||||
static Location evalFromRange(const Coord3& minCoord, const Coord3& maxCoord, Depth rangeDepth = MAX_DEPTH);
|
||||
|
||||
// Eval the intersection test against a frustum
|
||||
enum Intersection {
|
||||
Outside = 0,
|
||||
Intersect,
|
||||
Inside,
|
||||
};
|
||||
static Intersection intersectCell(const Location& cell, const Coord4f frustum[6]);
|
||||
|
||||
};
|
||||
using Locations = Location::vector;
|
||||
|
||||
// Cell or Brick Indexing
|
||||
using Index = ItemCell; // int32_t
|
||||
static const Index INVALID = -1;
|
||||
static const Index ROOT = 0;
|
||||
static const Index ROOT_CELL = 0;
|
||||
using Indices = std::vector<Index>;
|
||||
|
||||
// the cell description
|
||||
|
@ -230,6 +242,10 @@ namespace render {
|
|||
return _bricks[index];
|
||||
}
|
||||
|
||||
// Selection and traverse
|
||||
int select(ItemIDs& selection, const Coord4f frustum[6]) const;
|
||||
int selectTraverse(Index cellID, ItemIDs& selection, const Coord4f frustum[6]) const;
|
||||
|
||||
protected:
|
||||
Index allocateCell(Index parent, const Location& location);
|
||||
Index allocateBrick();
|
||||
|
@ -252,6 +268,7 @@ namespace render {
|
|||
double _invSize{ 1.0 / _size };
|
||||
glm::vec3 _origin{ -16384.0f };
|
||||
public:
|
||||
ItemSpatialTree() {}
|
||||
|
||||
float getSize() const { return _size; }
|
||||
const glm::vec3& getOrigin() const { return _origin; }
|
||||
|
@ -270,8 +287,11 @@ namespace render {
|
|||
auto npos = (pos - getOrigin());
|
||||
return Coord3(npos * getInvCellWidth(depth));
|
||||
}
|
||||
Coord3f evalCoordf(const glm::vec3& pos, Depth depth = Octree::MAX_DEPTH) const {
|
||||
auto npos = (pos - getOrigin());
|
||||
return Coord3f(npos * getInvCellWidth(depth));
|
||||
}
|
||||
|
||||
|
||||
// Bound to Location
|
||||
AABox evalBound(const Location& loc) const {
|
||||
float cellWidth = getCellWidth(loc.depth);
|
||||
|
@ -289,7 +309,10 @@ namespace render {
|
|||
|
||||
Index resetItem(Index oldCell, const Location& location, const ItemID& item);
|
||||
|
||||
ItemSpatialTree() {}
|
||||
// Selection and traverse
|
||||
int select(ItemIDs& selection, const ViewFrustum& frustum) const;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue