mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 13:49:12 +02:00
cleanup and speed up repeat traversals
This commit is contained in:
parent
b788273f47
commit
535d84abc7
3 changed files with 22 additions and 19 deletions
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
#include "EntityPriorityQueue.h"
|
#include "EntityPriorityQueue.h"
|
||||||
|
|
||||||
const float DO_NOT_SEND = -1.0e-6f;
|
const float PrioritizedEntity::DO_NOT_SEND = -1.0e-6f;
|
||||||
|
|
||||||
void ConicalView::set(const ViewFrustum& viewFrustum) {
|
void ConicalView::set(const ViewFrustum& viewFrustum) {
|
||||||
// The ConicalView has two parts: a central sphere (same as ViewFrustum) and a circular cone that bounds the frustum part.
|
// The ConicalView has two parts: a central sphere (same as ViewFrustum) and a circular cone that bounds the frustum part.
|
||||||
|
@ -47,7 +47,7 @@ float ConicalView::computePriority(const AACube& cube) const {
|
||||||
const float AVOID_DIVIDE_BY_ZERO = 0.001f;
|
const float AVOID_DIVIDE_BY_ZERO = 0.001f;
|
||||||
return r / (d + AVOID_DIVIDE_BY_ZERO);
|
return r / (d + AVOID_DIVIDE_BY_ZERO);
|
||||||
}
|
}
|
||||||
return DO_NOT_SEND;
|
return PrioritizedEntity::DO_NOT_SEND;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -68,7 +68,7 @@ float PrioritizedEntity::updatePriority(const ConicalView& conicalView) {
|
||||||
if (entity) {
|
if (entity) {
|
||||||
_priority = conicalView.computePriority(entity);
|
_priority = conicalView.computePriority(entity);
|
||||||
} else {
|
} else {
|
||||||
_priority = DO_NOT_SEND;
|
_priority = PrioritizedEntity::DO_NOT_SEND;
|
||||||
}
|
}
|
||||||
return _priority;
|
return _priority;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,8 @@ private:
|
||||||
// PrioritizedEntity is a placeholder in a sorted queue.
|
// PrioritizedEntity is a placeholder in a sorted queue.
|
||||||
class PrioritizedEntity {
|
class PrioritizedEntity {
|
||||||
public:
|
public:
|
||||||
|
static const float DO_NOT_SEND;
|
||||||
|
|
||||||
PrioritizedEntity(EntityItemPointer entity, float priority) : _weakEntity(entity), _rawEntityPointer(entity.get()), _priority(priority) {}
|
PrioritizedEntity(EntityItemPointer entity, float priority) : _weakEntity(entity), _rawEntityPointer(entity.get()), _priority(priority) {}
|
||||||
float updatePriority(const ConicalView& view);
|
float updatePriority(const ConicalView& view);
|
||||||
EntityItemPointer getEntity() const { return _weakEntity.lock(); }
|
EntityItemPointer getEntity() const { return _weakEntity.lock(); }
|
||||||
|
|
|
@ -85,20 +85,17 @@ void EntityTreeSendThread::preDistributionProcessing() {
|
||||||
|
|
||||||
void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,
|
void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,
|
||||||
bool viewFrustumChanged, bool isFullScene) {
|
bool viewFrustumChanged, bool isFullScene) {
|
||||||
// BEGIN EXPERIMENTAL DIFFERENTIAL TRAVERSAL
|
|
||||||
if (nodeData->getUsesFrustum()) {
|
if (nodeData->getUsesFrustum()) {
|
||||||
// DEBUG HACK: trigger traversal (Repeat) every so often
|
if (viewFrustumChanged || _traversal.finished()) {
|
||||||
const uint64_t TRAVERSE_AGAIN_PERIOD = 4 * USECS_PER_SECOND;
|
|
||||||
bool repeatTraversal = _traversal.finished() && usecTimestampNow() > _traversal.getStartOfCompletedTraversal() + TRAVERSE_AGAIN_PERIOD;
|
|
||||||
if (viewFrustumChanged || repeatTraversal) {
|
|
||||||
ViewFrustum viewFrustum;
|
ViewFrustum viewFrustum;
|
||||||
nodeData->copyCurrentViewFrustum(viewFrustum);
|
nodeData->copyCurrentViewFrustum(viewFrustum);
|
||||||
EntityTreeElementPointer root = std::dynamic_pointer_cast<EntityTreeElement>(_myServer->getOctree()->getRoot());
|
EntityTreeElementPointer root = std::dynamic_pointer_cast<EntityTreeElement>(_myServer->getOctree()->getRoot());
|
||||||
int32_t lodLevelOffset = nodeData->getBoundaryLevelAdjust() + (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
|
int32_t lodLevelOffset = nodeData->getBoundaryLevelAdjust() + (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
|
||||||
startNewTraversal(viewFrustum, root, lodLevelOffset);
|
startNewTraversal(viewFrustum, root, lodLevelOffset);
|
||||||
|
|
||||||
// If the previous traversal didn't finish, we'll need to resort the entities still in _sendQueue after calling traverse
|
// When the viewFrustum changed the sort order may be incorrect, so we re-sort
|
||||||
if (!_sendQueue.empty()) {
|
// and also use the opportunity to cull anything no longer in view
|
||||||
|
if (viewFrustumChanged && !_sendQueue.empty()) {
|
||||||
EntityPriorityQueue prevSendQueue;
|
EntityPriorityQueue prevSendQueue;
|
||||||
_sendQueue.swap(prevSendQueue);
|
_sendQueue.swap(prevSendQueue);
|
||||||
_entitiesInQueue.clear();
|
_entitiesInQueue.clear();
|
||||||
|
@ -111,9 +108,8 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
|
||||||
AACube cube = entity->getQueryAACube(success);
|
AACube cube = entity->getQueryAACube(success);
|
||||||
if (success) {
|
if (success) {
|
||||||
if (_traversal.getCurrentView().cubeIntersectsKeyhole(cube)) {
|
if (_traversal.getCurrentView().cubeIntersectsKeyhole(cube)) {
|
||||||
const float DO_NOT_SEND = -1.0e-6f;
|
|
||||||
float priority = _conicalView.computePriority(cube);
|
float priority = _conicalView.computePriority(cube);
|
||||||
if (priority != DO_NOT_SEND) {
|
if (priority != PrioritizedEntity::DO_NOT_SEND) {
|
||||||
float renderAccuracy = calculateRenderAccuracy(_traversal.getCurrentView().getPosition(),
|
float renderAccuracy = calculateRenderAccuracy(_traversal.getCurrentView().getPosition(),
|
||||||
cube,
|
cube,
|
||||||
_traversal.getCurrentRootSizeScale(),
|
_traversal.getCurrentRootSizeScale(),
|
||||||
|
@ -165,7 +161,6 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // SEND_SORTED_ENTITIES
|
#endif // SEND_SORTED_ENTITIES
|
||||||
// END EXPERIMENTAL DIFFERENTIAL TRAVERSAL
|
|
||||||
|
|
||||||
OctreeSendThread::traverseTreeAndSendContents(node, nodeData, viewFrustumChanged, isFullScene);
|
OctreeSendThread::traverseTreeAndSendContents(node, nodeData, viewFrustumChanged, isFullScene);
|
||||||
}
|
}
|
||||||
|
@ -250,6 +245,10 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
|
||||||
// larger octree cell because of its position (for example if it crosses the boundary of a cell it
|
// larger octree cell because of its position (for example if it crosses the boundary of a cell it
|
||||||
// pops to the next higher cell. So we want to check to see that the entity is large enough to be seen
|
// pops to the next higher cell. So we want to check to see that the entity is large enough to be seen
|
||||||
// before we consider including it.
|
// before we consider including it.
|
||||||
|
//
|
||||||
|
// TODO: compare priority against a threshold rather than bother with
|
||||||
|
// calculateRenderAccuracy(). Would need to replace all calculateRenderAccuracy()
|
||||||
|
// stuff everywhere with threshold in one sweep.
|
||||||
float renderAccuracy = calculateRenderAccuracy(_traversal.getCurrentView().getPosition(),
|
float renderAccuracy = calculateRenderAccuracy(_traversal.getCurrentView().getPosition(),
|
||||||
cube,
|
cube,
|
||||||
_traversal.getCurrentRootSizeScale(),
|
_traversal.getCurrentRootSizeScale(),
|
||||||
|
@ -272,14 +271,14 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
|
||||||
break;
|
break;
|
||||||
case DiffTraversal::Repeat:
|
case DiffTraversal::Repeat:
|
||||||
_traversal.setScanCallback([&] (DiffTraversal::VisibleElement& next) {
|
_traversal.setScanCallback([&] (DiffTraversal::VisibleElement& next) {
|
||||||
uint64_t timestamp = _traversal.getStartOfCompletedTraversal();
|
uint64_t startOfCompletedTraversal = _traversal.getStartOfCompletedTraversal();
|
||||||
if (next.element->getLastChangedContent() > timestamp) {
|
if (next.element->getLastChangedContent() > startOfCompletedTraversal) {
|
||||||
next.element->forEachEntity([&](EntityItemPointer entity) {
|
next.element->forEachEntity([&](EntityItemPointer entity) {
|
||||||
// Bail early if we've already checked this entity this frame
|
// Bail early if we've already checked this entity this frame
|
||||||
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
|
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (entity->getLastEdited() > timestamp) {
|
if (entity->getLastEdited() > startOfCompletedTraversal) {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
AACube cube = entity->getQueryAACube(success);
|
AACube cube = entity->getQueryAACube(success);
|
||||||
if (success) {
|
if (success) {
|
||||||
|
@ -310,8 +309,9 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
|
||||||
case DiffTraversal::Differential:
|
case DiffTraversal::Differential:
|
||||||
_traversal.setScanCallback([&] (DiffTraversal::VisibleElement& next) {
|
_traversal.setScanCallback([&] (DiffTraversal::VisibleElement& next) {
|
||||||
// NOTE: for Differential case: next.intersection is against completedView not currentView
|
// NOTE: for Differential case: next.intersection is against completedView not currentView
|
||||||
uint64_t timestamp = _traversal.getStartOfCompletedTraversal();
|
uint64_t startOfCompletedTraversal = _traversal.getStartOfCompletedTraversal();
|
||||||
if (next.element->getLastChangedContent() > timestamp || next.intersection != ViewFrustum::INSIDE) {
|
if (next.element->getLastChangedContent() > startOfCompletedTraversal ||
|
||||||
|
next.intersection != ViewFrustum::INSIDE) {
|
||||||
next.element->forEachEntity([&](EntityItemPointer entity) {
|
next.element->forEachEntity([&](EntityItemPointer entity) {
|
||||||
// Bail early if we've already checked this entity this frame
|
// Bail early if we've already checked this entity this frame
|
||||||
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
|
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
|
||||||
|
@ -329,7 +329,8 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
|
||||||
|
|
||||||
// Only send entities if they are large enough to see
|
// Only send entities if they are large enough to see
|
||||||
if (renderAccuracy > 0.0f) {
|
if (renderAccuracy > 0.0f) {
|
||||||
if (entity->getLastEdited() > timestamp || !_traversal.getCompletedView().cubeIntersectsKeyhole(cube)) {
|
if (entity->getLastEdited() > startOfCompletedTraversal ||
|
||||||
|
!_traversal.getCompletedView().cubeIntersectsKeyhole(cube)) {
|
||||||
float priority = _conicalView.computePriority(cube);
|
float priority = _conicalView.computePriority(cube);
|
||||||
_sendQueue.push(PrioritizedEntity(entity, priority));
|
_sendQueue.push(PrioritizedEntity(entity, priority));
|
||||||
_entitiesInQueue.insert(entity.get());
|
_entitiesInQueue.insert(entity.get());
|
||||||
|
|
Loading…
Reference in a new issue