mirror of
https://github.com/overte-org/overte.git
synced 2025-04-23 23:53:26 +02:00
more correct handling of LOD
This commit is contained in:
parent
8b7c43f3b1
commit
3e50d01734
4 changed files with 36 additions and 44 deletions
|
@ -95,7 +95,8 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
|
|||
ViewFrustum viewFrustum;
|
||||
nodeData->copyCurrentViewFrustum(viewFrustum);
|
||||
EntityTreeElementPointer root = std::dynamic_pointer_cast<EntityTreeElement>(_myServer->getOctree()->getRoot());
|
||||
startNewTraversal(viewFrustum, root);
|
||||
int32_t lodLevelOffset = nodeData->getBoundaryLevelAdjust() + (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
|
||||
startNewTraversal(viewFrustum, root, lodLevelOffset);
|
||||
}
|
||||
}
|
||||
if (!_traversal.finished()) {
|
||||
|
@ -172,8 +173,8 @@ bool EntityTreeSendThread::addDescendantsToExtraFlaggedEntities(const QUuid& fil
|
|||
return hasNewChild || hasNewDescendants;
|
||||
}
|
||||
|
||||
void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root) {
|
||||
DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root);
|
||||
void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root, int32_t lodLevelOffset) {
|
||||
DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, lodLevelOffset);
|
||||
// there are three types of traversal:
|
||||
//
|
||||
// (1) FirstTime = at login --> find everything in view
|
||||
|
|
|
@ -36,7 +36,7 @@ private:
|
|||
bool addAncestorsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData);
|
||||
bool addDescendantsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData);
|
||||
|
||||
void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root);
|
||||
void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset);
|
||||
|
||||
DiffTraversal _traversal;
|
||||
EntityPriorityQueue _sendQueue;
|
||||
|
|
|
@ -34,7 +34,7 @@ void DiffTraversal::Waypoint::getNextVisibleElementFirstTime(DiffTraversal::Visi
|
|||
EntityTreeElementPointer element = _weakElement.lock();
|
||||
if (element) {
|
||||
// check for LOD truncation
|
||||
float visibleLimit = boundaryDistanceForRenderLevel(element->getLevel() + view.rootLevel, view.rootSizeScale);
|
||||
float visibleLimit = boundaryDistanceForRenderLevel(element->getLevel() + view.lodLevelOffset, view.rootSizeScale);
|
||||
float distance2 = glm::distance2(view.viewFrustum.getPosition(), element->getAACube().calcCenter());
|
||||
if (distance2 < visibleLimit * visibleLimit) {
|
||||
while (_nextIndex < NUMBER_OF_CHILDREN) {
|
||||
|
@ -67,7 +67,7 @@ void DiffTraversal::Waypoint::getNextVisibleElementRepeat(
|
|||
EntityTreeElementPointer element = _weakElement.lock();
|
||||
if (element) {
|
||||
// check for LOD truncation
|
||||
float visibleLimit = boundaryDistanceForRenderLevel(element->getLevel() - view.rootLevel + 1, view.rootSizeScale);
|
||||
float visibleLimit = boundaryDistanceForRenderLevel(element->getLevel() + view.lodLevelOffset, view.rootSizeScale);
|
||||
float distance2 = glm::distance2(view.viewFrustum.getPosition(), element->getAACube().calcCenter());
|
||||
if (distance2 < visibleLimit * visibleLimit) {
|
||||
while (_nextIndex < NUMBER_OF_CHILDREN) {
|
||||
|
@ -95,12 +95,12 @@ DiffTraversal::DiffTraversal() {
|
|||
}
|
||||
|
||||
void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::VisibleElement& next,
|
||||
const DiffTraversal::View& view, const DiffTraversal::View& lastView, uint64_t lastTime) {
|
||||
const DiffTraversal::View& view, const DiffTraversal::View& lastView) {
|
||||
if (_nextIndex == -1) {
|
||||
// root case is special
|
||||
++_nextIndex;
|
||||
EntityTreeElementPointer element = _weakElement.lock();
|
||||
if (element->getLastChangedContent() > lastTime) {
|
||||
if (element->getLastChangedContent() > lastView.startTime) {
|
||||
next.element = element;
|
||||
next.intersection = ViewFrustum::INTERSECT;
|
||||
return;
|
||||
|
@ -110,7 +110,7 @@ void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::V
|
|||
EntityTreeElementPointer element = _weakElement.lock();
|
||||
if (element) {
|
||||
// check for LOD truncation
|
||||
uint32_t level = element->getLevel() - view.rootLevel + 1;
|
||||
int32_t level = element->getLevel() + view.lodLevelOffset;
|
||||
float visibleLimit = boundaryDistanceForRenderLevel(level, view.rootSizeScale);
|
||||
float distance2 = glm::distance2(view.viewFrustum.getPosition(), element->getAACube().calcCenter());
|
||||
if (distance2 < visibleLimit * visibleLimit) {
|
||||
|
@ -121,7 +121,7 @@ void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::V
|
|||
AACube cube = nextElement->getAACube();
|
||||
if ( view.viewFrustum.calculateCubeKeyholeIntersection(cube) != ViewFrustum::OUTSIDE) {
|
||||
ViewFrustum::intersection lastIntersection = lastView.viewFrustum.calculateCubeKeyholeIntersection(cube);
|
||||
if (!(lastIntersection == ViewFrustum::INSIDE && nextElement->getLastChanged() < lastTime)) {
|
||||
if (!(lastIntersection == ViewFrustum::INSIDE && nextElement->getLastChanged() < lastView.startTime)) {
|
||||
next.element = nextElement;
|
||||
// NOTE: for differential case next.intersection is against the lastView
|
||||
// because this helps the "external scan" optimize its culling
|
||||
|
@ -130,10 +130,8 @@ void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::V
|
|||
} else {
|
||||
// check for LOD truncation in the last traversal because
|
||||
// we may need to traverse this element after all if the lastView skipped it for LOD
|
||||
//
|
||||
// NOTE: the element's "level" must be invariant (the differntial algorithm doesn't work otherwise)
|
||||
// so we recycle the value computed higher up
|
||||
visibleLimit = boundaryDistanceForRenderLevel(level, lastView.rootSizeScale);
|
||||
int32_t lastLevel = element->getLevel() + lastView.lodLevelOffset;
|
||||
visibleLimit = boundaryDistanceForRenderLevel(lastLevel, lastView.rootSizeScale);
|
||||
distance2 = glm::distance2(lastView.viewFrustum.getPosition(), element->getAACube().calcCenter());
|
||||
if (distance2 >= visibleLimit * visibleLimit) {
|
||||
next.element = nextElement;
|
||||
|
@ -151,7 +149,9 @@ void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::V
|
|||
next.intersection = ViewFrustum::OUTSIDE;
|
||||
}
|
||||
|
||||
DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root) {
|
||||
DiffTraversal::Type DiffTraversal::prepareNewTraversal(
|
||||
const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset) {
|
||||
assert(root);
|
||||
// there are three types of traversal:
|
||||
//
|
||||
// (1) First = fresh view --> find all elements in view
|
||||
|
@ -167,39 +167,36 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFr
|
|||
// external code should update the _scanElementCallback after calling prepareNewTraversal
|
||||
//
|
||||
|
||||
Type type = Type::First;
|
||||
if (_startOfCompletedTraversal == 0) {
|
||||
// first time
|
||||
Type type;
|
||||
if (_completedView.startTime == 0) {
|
||||
type = Type::First;
|
||||
_currentView.viewFrustum = viewFrustum;
|
||||
_currentView.lodLevelOffset = root->getLevel() + lodLevelOffset - 1; // -1 because true root has level=1
|
||||
_currentView.rootSizeScale = root->getScale() * MAX_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT;
|
||||
_getNextVisibleElementCallback = [&](DiffTraversal::VisibleElement& next) {
|
||||
_path.back().getNextVisibleElementFirstTime(next, _currentView);
|
||||
};
|
||||
} else if (_currentView.viewFrustum.isVerySimilar(viewFrustum)) {
|
||||
// again
|
||||
_getNextVisibleElementCallback = [&](DiffTraversal::VisibleElement& next) {
|
||||
_path.back().getNextVisibleElementRepeat(next, _currentView, _startOfCompletedTraversal);
|
||||
};
|
||||
} else if (_completedView.viewFrustum.isVerySimilar(viewFrustum) && lodLevelOffset == _completedView.lodLevelOffset) {
|
||||
type = Type::Repeat;
|
||||
} else {
|
||||
// differential
|
||||
_currentView.viewFrustum = viewFrustum;
|
||||
_getNextVisibleElementCallback = [&](DiffTraversal::VisibleElement& next) {
|
||||
_path.back().getNextVisibleElementDifferential(next, _currentView, _completedView, _startOfCompletedTraversal);
|
||||
_path.back().getNextVisibleElementRepeat(next, _completedView, _completedView.startTime);
|
||||
};
|
||||
} else {
|
||||
type = Type::Differential;
|
||||
_currentView.viewFrustum = viewFrustum;
|
||||
_currentView.lodLevelOffset = root->getLevel() + lodLevelOffset - 1; // -1 because true root has level=1
|
||||
_currentView.rootSizeScale = root->getScale() * MAX_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT;
|
||||
_getNextVisibleElementCallback = [&](DiffTraversal::VisibleElement& next) {
|
||||
_path.back().getNextVisibleElementDifferential(next, _currentView, _completedView);
|
||||
};
|
||||
}
|
||||
|
||||
assert(root);
|
||||
_path.clear();
|
||||
_path.push_back(DiffTraversal::Waypoint(root));
|
||||
// set root fork's index such that root element returned at getNextElement()
|
||||
_path.back().initRootNextIndex();
|
||||
|
||||
// cache LOD parameters in the _currentView
|
||||
_currentView.rootLevel = root->getLevel();
|
||||
_currentView.rootSizeScale = root->getScale() * MAX_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT;
|
||||
|
||||
_startOfCurrentTraversal = usecTimestampNow();
|
||||
_currentView.startTime = usecTimestampNow();
|
||||
|
||||
return type;
|
||||
}
|
||||
|
@ -224,7 +221,6 @@ void DiffTraversal::getNextVisibleElement(DiffTraversal::VisibleElement& next) {
|
|||
if (_path.empty()) {
|
||||
// we've traversed the entire tree
|
||||
_completedView = _currentView;
|
||||
_startOfCompletedTraversal = _startOfCurrentTraversal;
|
||||
return;
|
||||
}
|
||||
// keep looking for next
|
||||
|
|
|
@ -33,8 +33,9 @@ public:
|
|||
class View {
|
||||
public:
|
||||
ViewFrustum viewFrustum;
|
||||
uint64_t startTime { 0 };
|
||||
float rootSizeScale { 1.0f };
|
||||
float rootLevel { 0.0f };
|
||||
int32_t lodLevelOffset { 0 };
|
||||
};
|
||||
|
||||
// Waypoint is an bookmark in a "path" of waypoints during a traversal.
|
||||
|
@ -44,7 +45,7 @@ public:
|
|||
|
||||
void getNextVisibleElementFirstTime(VisibleElement& next, const View& view);
|
||||
void getNextVisibleElementRepeat(VisibleElement& next, const View& view, uint64_t lastTime);
|
||||
void getNextVisibleElementDifferential(VisibleElement& next, const View& view, const View& lastView, uint64_t lastTime);
|
||||
void getNextVisibleElementDifferential(VisibleElement& next, const View& view, const View& lastView);
|
||||
|
||||
int8_t getNextIndex() const { return _nextIndex; }
|
||||
void initRootNextIndex() { _nextIndex = -1; }
|
||||
|
@ -58,12 +59,12 @@ public:
|
|||
|
||||
DiffTraversal();
|
||||
|
||||
DiffTraversal::Type prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root);
|
||||
Type prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset);
|
||||
|
||||
const ViewFrustum& getCurrentView() const { return _currentView.viewFrustum; }
|
||||
const ViewFrustum& getCompletedView() const { return _completedView.viewFrustum; }
|
||||
|
||||
uint64_t getStartOfCompletedTraversal() const { return _startOfCompletedTraversal; }
|
||||
uint64_t getStartOfCompletedTraversal() const { return _completedView.startTime; }
|
||||
bool finished() const { return _path.empty(); }
|
||||
|
||||
void setScanCallback(std::function<void (VisibleElement&)> cb);
|
||||
|
@ -79,12 +80,6 @@ private:
|
|||
std::vector<Waypoint> _path;
|
||||
std::function<void (VisibleElement&)> _getNextVisibleElementCallback { nullptr };
|
||||
std::function<void (VisibleElement&)> _scanElementCallback { [](VisibleElement& e){} };
|
||||
uint64_t _startOfCompletedTraversal { 0 };
|
||||
uint64_t _startOfCurrentTraversal { 0 };
|
||||
|
||||
// LOD stuff
|
||||
float _rootSizeScale { 1.0f };
|
||||
uint32_t _rootLevel { 0 };
|
||||
};
|
||||
|
||||
#endif // hifi_EntityPriorityQueue_h
|
||||
|
|
Loading…
Reference in a new issue