1
0
Fork 0

Ensure transient octrees bypass the NavCache

This commit is contained in:
James Turner 2021-06-11 09:57:04 +01:00
parent a17180f5b0
commit 72ec70f275
2 changed files with 66 additions and 65 deletions

View file

@ -43,8 +43,8 @@ namespace flightgear
namespace Octree namespace Octree
{ {
std::unique_ptr<Node> global_spatialOctree; static std::unique_ptr<Node> global_spatialOctree;
std::unique_ptr<Node> global_transientOctree; static std::unique_ptr<Node> global_transientOctree;
double RADIUS_EARTH_M = 7000 * 1000.0; // 7000km is plenty double RADIUS_EARTH_M = 7000 * 1000.0; // 7000km is plenty
@ -98,9 +98,11 @@ Node *Node::findNodeForBox(const SGBoxd&) const
return const_cast<Node*>(this); return const_cast<Node*>(this);
} }
Leaf::Leaf(const SGBoxd& aBox, int64_t aIdent, bool persistent) : Node(aBox, aIdent, persistent), Leaf::Leaf(const SGBoxd& aBox, int64_t aIdent, bool persistent) : Node(aBox, aIdent, persistent)
childrenLoaded(false)
{ {
if (!persistent) {
_childrenLoaded = true;
}
} }
void Leaf::visit(const SGVec3d& aPos, double aCutoff, void Leaf::visit(const SGVec3d& aPos, double aCutoff,
@ -152,9 +154,9 @@ void Leaf::insertChild(FGPositioned::Type ty, PositionedID id)
void Leaf::loadChildren() void Leaf::loadChildren()
{ {
if (childrenLoaded) { if (_childrenLoaded) {
return; return;
} }
NavDataCache* cache = NavDataCache::instance(); NavDataCache* cache = NavDataCache::instance();
for (const auto& tp : cache->getOctreeLeafChildren(guid())) { for (const auto& tp : cache->getOctreeLeafChildren(guid())) {
@ -162,15 +164,17 @@ void Leaf::loadChildren()
children.insert(children.end(), tp); children.insert(children.end(), tp);
} // of leaf members iteration } // of leaf members iteration
childrenLoaded = true; _childrenLoaded = true;
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
Branch::Branch(const SGBoxd& aBox, int64_t aIdent, bool persistent) : Node(aBox, aIdent, persistent), Branch::Branch(const SGBoxd& aBox, int64_t aIdent, bool persistent) : Node(aBox, aIdent, persistent)
childrenLoaded(false)
{ {
memset(children, 0, sizeof(Node*) * 8); _children.fill(nullptr);
if (!_persistent) {
_childrenLoaded = true;
}
} }
void Branch::visit(const SGVec3d& aPos, double aCutoff, void Branch::visit(const SGVec3d& aPos, double aCutoff,
@ -179,16 +183,16 @@ void Branch::visit(const SGVec3d& aPos, double aCutoff,
{ {
loadChildren(); loadChildren();
for (unsigned int i=0; i<8; ++i) { for (unsigned int i=0; i<8; ++i) {
if (!children[i]) { if (!_children[i]) {
continue; continue;
}
double d = _children[i]->distToNearest(aPos);
if (d > aCutoff) {
continue; // exceeded cutoff
} }
double d = children[i]->distToNearest(aPos); aQ.push(Ordered<Node*>(_children[i], d));
if (d > aCutoff) {
continue; // exceeded cutoff
}
aQ.push(Ordered<Node*>(children[i], d));
} // of child iteration } // of child iteration
} }
@ -200,16 +204,16 @@ void Branch::visitForLines(const SGVec3d& aPos, double aCutoff,
Node::visitForLines(aPos, aCutoff, aLines, aQ); Node::visitForLines(aPos, aCutoff, aLines, aQ);
for (unsigned int i=0; i<8; ++i) { for (unsigned int i=0; i<8; ++i) {
if (!children[i]) { if (!_children[i]) {
continue; continue;
} }
double d = children[i]->distToNearest(aPos); double d = _children[i]->distToNearest(aPos);
if (d > aCutoff) { if (d > aCutoff) {
continue; // exceeded cutoff continue; // exceeded cutoff
} }
aQ.push_back(children[i]); aQ.push_back(_children[i]);
} // of child iteration } // of child iteration
} }
@ -266,46 +270,42 @@ Node* Branch::childForPos(const SGVec3d& aCart) const
Node* Branch::childAtIndex(int childIndex) const Node* Branch::childAtIndex(int childIndex) const
{ {
Node* child = children[childIndex]; Node* child = _children[childIndex];
if (!child) { // lazy building of children if (!child) { // lazy building of children
SGBoxd cb(boxForChild(childIndex)); SGBoxd cb(boxForChild(childIndex));
double d2 = dot(cb.getSize(), cb.getSize()); double d2 = dot(cb.getSize(), cb.getSize());
assert(((_ident << 3) >> 3) == _ident); assert(((_ident << 3) >> 3) == _ident);
// child index is 0..7, so 3-bits is sufficient, and hence we can // child index is 0..7, so 3-bits is sufficient, and hence we can
// pack 20 levels of octree into a int64, which is plenty // pack 20 levels of octree into a int64, which is plenty
int64_t childIdent = (_ident << 3) | childIndex; int64_t childIdent = (_ident << 3) | childIndex;
if (d2 < LEAF_SIZE_SQR) { if (d2 < LEAF_SIZE_SQR) {
// REVIEW: Memory Leak - 480 bytes in 3 blocks are still reachable // REVIEW: Memory Leak - 480 bytes in 3 blocks are still reachable
child = new Leaf(cb, childIdent, _persistent); child = new Leaf(cb, childIdent, _persistent);
} else { } else {
// REVIEW: Memory Leak - 9,152 bytes in 52 blocks are still reachable // REVIEW: Memory Leak - 9,152 bytes in 52 blocks are still reachable
child = new Branch(cb, childIdent, _persistent); child = new Branch(cb, childIdent, _persistent);
} }
children[childIndex] = child; _children[childIndex] = child;
if (_persistent && childrenLoaded) { if (_persistent && _childrenLoaded) {
// childrenLoad is done, so we're defining a new node - add it to the // childrenLoad is done, so we're defining a new node - add it to the
// cache too. // cache too.
NavDataCache::instance()->defineOctreeNode(const_cast<Branch*>(this), child); NavDataCache::instance()->defineOctreeNode(const_cast<Branch*>(this), child);
} }
} }
return children[childIndex]; return _children[childIndex];
} }
void Branch::loadChildren() const void Branch::loadChildren() const
{ {
if (childrenLoaded) { if (_childrenLoaded) {
return; return;
} }
if (!_persistent) {
childrenLoaded = true;
}
int childrenMask = NavDataCache::instance()->getOctreeBranchChildren(guid()); int childrenMask = NavDataCache::instance()->getOctreeBranchChildren(guid());
for (int i=0; i<8; ++i) { for (int i=0; i<8; ++i) {
@ -316,16 +316,16 @@ void Branch::loadChildren() const
// set this after creating the child nodes, so the cache update logic // set this after creating the child nodes, so the cache update logic
// in childAtIndex knows any future created children need to be added. // in childAtIndex knows any future created children need to be added.
childrenLoaded = true; _childrenLoaded = true;
} }
int Branch::childMask() const int Branch::childMask() const
{ {
int result = 0; int result = 0;
for (int i=0; i<8; ++i) { for (int i=0; i<8; ++i) {
if (children[i]) { if (_children[i]) {
result |= 1 << i; result |= 1 << i;
} }
} }
return result; return result;

View file

@ -25,12 +25,13 @@
#define FG_POSITIONED_OCTREE_HXX #define FG_POSITIONED_OCTREE_HXX
// std // std
#include <vector> #include <array>
#include <set>
#include <queue>
#include <cassert> #include <cassert>
#include <map>
#include <functional> #include <functional>
#include <map>
#include <queue>
#include <set>
#include <vector>
// SimGear // SimGear
#include <simgear/math/SGGeometry.hxx> #include <simgear/math/SGGeometry.hxx>
@ -194,12 +195,12 @@ namespace Octree
void insertChild(FGPositioned::Type ty, PositionedID id); void insertChild(FGPositioned::Type ty, PositionedID id);
private: private:
bool childrenLoaded; bool _childrenLoaded = false;
typedef std::multimap<FGPositioned::Type, PositionedID> ChildMap; typedef std::multimap<FGPositioned::Type, PositionedID> ChildMap;
ChildMap children; ChildMap children;
void loadChildren(); void loadChildren();
}; };
class Branch : public Node class Branch : public Node
@ -241,8 +242,8 @@ namespace Octree
void loadChildren() const; void loadChildren() const;
mutable Node* children[8]; mutable std::array<Node*, 8> _children;
mutable bool childrenLoaded; mutable bool _childrenLoaded = false;
}; };
bool findNearestN(const SGVec3d& aPos, unsigned int aN, double aCutoffM, FGPositioned::Filter* aFilter, FGPositionedList& aResults, int aCutoffMsec); bool findNearestN(const SGVec3d& aPos, unsigned int aN, double aCutoffM, FGPositioned::Filter* aFilter, FGPositionedList& aResults, int aCutoffMsec);