full scene traversal and json filters

This commit is contained in:
SamGondelman 2017-09-01 14:13:43 -07:00 committed by Andrew Meadows
parent 0ad5f47bfd
commit 7938e301e7
6 changed files with 82 additions and 25 deletions

View file

@ -98,7 +98,7 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
nodeData->copyCurrentViewFrustum(viewFrustum);
EntityTreeElementPointer root = std::dynamic_pointer_cast<EntityTreeElement>(_myServer->getOctree()->getRoot());
int32_t lodLevelOffset = nodeData->getBoundaryLevelAdjust() + (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
startNewTraversal(viewFrustum, root, lodLevelOffset);
startNewTraversal(viewFrustum, root, lodLevelOffset, true);
// When the viewFrustum changed the sort order may be incorrect, so we re-sort
// and also use the opportunity to cull anything no longer in view
@ -138,6 +138,11 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
}
}
}
} else if (_traversal.finished()) {
ViewFrustum viewFrustum;
EntityTreeElementPointer root = std::dynamic_pointer_cast<EntityTreeElement>(_myServer->getOctree()->getRoot());
int32_t lodLevelOffset = nodeData->getBoundaryLevelAdjust() + NO_BOUNDARY_ADJUST;
startNewTraversal(viewFrustum, root, lodLevelOffset, false);
}
if (!_traversal.finished()) {
@ -165,7 +170,7 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
EntityItemPointer entity = entry.getEntity();
if (entity) {
std::cout << "adebug send '" << entity->getName().toStdString() << "'" << " : " << entry.getPriority() << std::endl; // adebug
_knownState[entity] = sendTime;
_knownState[entity.get()] = sendTime;
}
_sendQueue.pop();
_entitiesInQueue.erase(entry.getRawEntityPointer());
@ -225,13 +230,14 @@ bool EntityTreeSendThread::addDescendantsToExtraFlaggedEntities(const QUuid& fil
return hasNewChild || hasNewDescendants;
}
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:
void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesFrustum) {
DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, lodLevelOffset, usesFrustum);
// there are four types of traversal:
//
// (1) FirstTime = at login --> find everything in view
// (2) Repeat = view hasn't changed --> find what has changed since last complete traversal
// (3) Differential = view has changed --> find what has changed or in new view but not old
// (4) FullScene = no view frustum -> send everything
//
// The "scanCallback" we provide to the traversal depends on the type:
//
@ -371,10 +377,26 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
}
});
break;
case DiffTraversal::FullScene:
_traversal.setScanCallback([&](DiffTraversal::VisibleElement& next) {
next.element->forEachEntity([&](EntityItemPointer entity) {
// Bail early if we've already checked this entity this frame
if (_entitiesInQueue.find(entity.get()) != _entitiesInQueue.end()) {
return;
}
if (_knownState.find(entity.get()) == _knownState.end() ||
(_knownState.find(entity.get()) != _knownState.end() && entity->getLastEdited() > _knownState[entity.get()])) {
// We don't have a view frustum from which to compute priority
_sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
_entitiesInQueue.insert(entity.get());
}
});
});
break;
}
}
bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params) {
bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) {
#ifdef SEND_SORTED_ENTITIES
//auto entityTree = std::static_pointer_cast<EntityTree>(_myServer->getOctree());
if (_sendQueue.empty()) {
@ -418,17 +440,20 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream
PrioritizedEntity queuedItem = _sendQueue.top();
EntityItemPointer entity = queuedItem.getEntity();
if (entity) {
OctreeElement::AppendState appendEntityState = entity->appendEntityData(&_packetData, params, _extraEncodeData);
_knownState[entity.get()] = sendTime;
// Only send entities that match the jsonFilters, but keep track of everything we've tried to send so we don't try to send it again
if (entity->matchesJSONFilters(jsonFilters)) {
OctreeElement::AppendState appendEntityState = entity->appendEntityData(&_packetData, params, _extraEncodeData);
if (appendEntityState != OctreeElement::COMPLETED) {
if (appendEntityState == OctreeElement::PARTIAL) {
++_numEntities;
if (appendEntityState != OctreeElement::COMPLETED) {
if (appendEntityState == OctreeElement::PARTIAL) {
++_numEntities;
}
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
break;
}
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
break;
++_numEntities;
}
++_numEntities;
_knownState[entity.get()] = sendTime;
}
_sendQueue.pop();
_entitiesInQueue.erase(entity.get());

View file

@ -39,8 +39,8 @@ 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, int32_t lodLevelOffset);
bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params) override;
void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesFrustum);
bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) override;
DiffTraversal _traversal;
EntityPriorityQueue _sendQueue;

View file

@ -458,7 +458,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
return _truePacketsSent;
}
bool OctreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params) {
bool OctreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) {
bool somethingToSend = false;
OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(params.nodeData);
if (!nodeData->elementBag.isEmpty()) {
@ -523,7 +523,7 @@ void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, Octre
bool lastNodeDidntFit = false; // assume each node fits
params.stopReason = EncodeBitstreamParams::UNKNOWN; // reset params.stopReason before traversal
somethingToSend = traverseTreeAndBuildNextPacketPayload(params);
somethingToSend = traverseTreeAndBuildNextPacketPayload(params, nodeData->getJSONParameters());
if (params.stopReason == EncodeBitstreamParams::DIDNT_FIT) {
lastNodeDidntFit = true;

View file

@ -55,7 +55,7 @@ protected:
virtual void preDistributionProcessing() {};
virtual void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,
bool viewFrustumChanged, bool isFullScene);
virtual bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params);
virtual bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters);
OctreePacketData _packetData;
QWeakPointer<Node> _node;

View file

@ -142,19 +142,45 @@ void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::V
next.intersection = ViewFrustum::OUTSIDE;
}
void DiffTraversal::Waypoint::getNextVisibleElementFullScene(DiffTraversal::VisibleElement& next, uint64_t lastTime) {
// NOTE: no need to set next.intersection or check LOD truncation in the "FullScene" context
if (_nextIndex == -1) {
++_nextIndex;
EntityTreeElementPointer element = _weakElement.lock();
if (element->getLastChangedContent() > lastTime) {
next.element = element;
return;
}
}
if (_nextIndex < NUMBER_OF_CHILDREN) {
EntityTreeElementPointer element = _weakElement.lock();
if (element) {
while (_nextIndex < NUMBER_OF_CHILDREN) {
EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex);
++_nextIndex;
if (nextElement && nextElement->getLastChanged() > lastTime) {
next.element = nextElement;
return;
}
}
}
}
next.element.reset();
}
DiffTraversal::DiffTraversal() {
const int32_t MIN_PATH_DEPTH = 16;
_path.reserve(MIN_PATH_DEPTH);
}
DiffTraversal::Type DiffTraversal::prepareNewTraversal(
const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset) {
DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesFrustum) {
assert(root);
// there are three types of traversal:
// there are four types of traversal:
//
// (1) First = fresh view --> find all elements in view
// (2) Repeat = view hasn't changed --> find elements changed since last complete traversal
// (3) Differential = view has changed --> find elements changed or in new view but not old
// (4) FullScene = no view frustum -> send everything
//
// for each traversal type we assign the appropriate _getNextVisibleElementCallback
//
@ -166,7 +192,12 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(
//
Type type;
if (_completedView.startTime == 0) {
if (!usesFrustum) {
type = Type::FullScene;
_getNextVisibleElementCallback = [&](DiffTraversal::VisibleElement& next) {
_path.back().getNextVisibleElementFullScene(next, _completedView.startTime);
};
} else if (_completedView.startTime == 0) {
type = Type::First;
_currentView.viewFrustum = viewFrustum;
_currentView.lodLevelOffset = root->getLevel() + lodLevelOffset - 1; // -1 because true root has level=1

View file

@ -46,6 +46,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);
void getNextVisibleElementFullScene(VisibleElement& next, uint64_t lastTime);
int8_t getNextIndex() const { return _nextIndex; }
void initRootNextIndex() { _nextIndex = -1; }
@ -55,11 +56,11 @@ public:
int8_t _nextIndex;
};
typedef enum { First, Repeat, Differential } Type;
typedef enum { First, Repeat, Differential, FullScene } Type;
DiffTraversal();
Type prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset);
Type prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, bool isFullScene);
const ViewFrustum& getCurrentView() const { return _currentView.viewFrustum; }
const ViewFrustum& getCompletedView() const { return _completedView.viewFrustum; }