first-pass sending entities from _sendQueue

This commit is contained in:
Andrew Meadows 2017-08-23 14:56:55 -07:00
parent 1562fb153e
commit b6818c4369
4 changed files with 99 additions and 15 deletions

View file

@ -17,6 +17,8 @@
#include "EntityServer.h"
//#define SEND_SORTED_ENTITIES
void EntityTreeSendThread::preDistributionProcessing() {
auto node = _node.toStrongRef();
auto nodeData = static_cast<EntityNodeData*>(node->getLinkedData());
@ -145,6 +147,7 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
std::cout << "adebug traversal complete " << " Q.size = " << _sendQueue.size() << " dt = " << dt << std::endl; // adebug
}
#ifndef SEND_SORTED_ENTITIES
if (!_sendQueue.empty()) {
// print what needs to be sent
while (!_sendQueue.empty()) {
@ -157,6 +160,7 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O
_entitiesToSend.erase(entity);
}
}
#endif // SEND_SORTED_ENTITIES
// END EXPERIMENTAL DIFFERENTIAL TRAVERSAL
OctreeSendThread::traverseTreeAndSendContents(node, nodeData, viewFrustumChanged, isFullScene);
@ -245,7 +249,7 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
float renderAccuracy = calculateRenderAccuracy(_traversal.getCurrentView().getPosition(),
cube,
_traversal.getCurrentRootSizeScale(),
lodLevelOffset);
_traversal.getCurrentLODOffset());
// Only send entities if they are large enough to see
if (renderAccuracy > 0.0f) {
@ -280,7 +284,7 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
float renderAccuracy = calculateRenderAccuracy(_traversal.getCurrentView().getPosition(),
cube,
_traversal.getCurrentRootSizeScale(),
lodLevelOffset);
_traversal.getCurrentLODOffset());
// Only send entities if they are large enough to see
if (renderAccuracy > 0.0f) {
@ -317,7 +321,7 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
float renderAccuracy = calculateRenderAccuracy(_traversal.getCurrentView().getPosition(),
cube,
_traversal.getCurrentRootSizeScale(),
lodLevelOffset);
_traversal.getCurrentLODOffset());
// Only send entities if they are large enough to see
if (renderAccuracy > 0.0f) {
@ -330,7 +334,7 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
float lastRenderAccuracy = calculateRenderAccuracy(_traversal.getCompletedView().getPosition(),
cube,
_traversal.getCompletedRootSizeScale(),
lodLevelOffset);
_traversal.getCompletedLODOffset());
if (lastRenderAccuracy <= 0.0f) {
float priority = _conicalView.computePriority(cube);
@ -352,3 +356,77 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
}
}
bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params) {
#ifdef SEND_SORTED_ENTITIES
//auto entityTree = std::static_pointer_cast<EntityTree>(_myServer->getOctree());
if (_sendQueue.empty()) {
return false;
}
if (!_packetData.hasContent()) {
// This is the beginning of a new packet.
// We pack minimal data for this to be accepted as an OctreeElement payload for the root element.
// The Octree header bytes look like this:
//
// 0x00 octalcode for root
// 0x00 colors (1 bit where recipient should call: child->readElementDataFromBuffer())
// 0xXX childrenInTreeMask (when params.includeExistsBits is true: 1 bit where child is existant)
// 0x00 childrenInBufferMask (1 bit where recipient should call: child->readElementData() recursively)
const uint8_t zeroByte = 0;
_packetData.appendValue(zeroByte); // octalcode
_packetData.appendValue(zeroByte); // colors
if (params.includeExistsBits) {
uint8_t childrenExistBits = 0;
EntityTreeElementPointer root = std::dynamic_pointer_cast<EntityTreeElement>(_myServer->getOctree()->getRoot());
for (int32_t i = 0; i < NUMBER_OF_CHILDREN; ++i) {
if (root->getChildAtIndex(i)) {
childrenExistBits += (1 << i);
}
}
_packetData.appendValue(childrenExistBits); // childrenInTreeMask
}
_packetData.appendValue(zeroByte); // childrenInBufferMask
// Pack zero for numEntities.
// But before we do: grab current byteOffset so we can come back later
// and update this with the real number.
_numEntities = 0;
_numEntitiesOffset = _packetData.getUncompressedByteOffset();
_packetData.appendValue(_numEntities);
}
LevelDetails entitiesLevel = _packetData.startLevel();
while(!_sendQueue.empty()) {
PrioritizedEntity queuedItem = _sendQueue.top();
EntityItemPointer entity = queuedItem.getEntity();
if (entity) {
OctreeElement::AppendState appendEntityState = entity->appendEntityData(&_packetData, params, _extraEncodeData);
if (appendEntityState != OctreeElement::COMPLETED) {
if (appendEntityState == OctreeElement::PARTIAL) {
++_numEntities;
}
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
break;
}
++_numEntities;
}
_sendQueue.pop();
}
if (_sendQueue.empty()) {
params.stopReason = EncodeBitstreamParams::FINISHED;
_extraEncodeData->entities.clear();
}
if (_numEntities == 0) {
_packetData.discardLevel(entitiesLevel);
return false;
}
_packetData.endLevel(entitiesLevel);
_packetData.updatePriorBytes(_numEntitiesOffset, (const unsigned char*)&_numEntities, sizeof(_numEntities));
return true;
#else // SEND_SORTED_ENTITIES
return OctreeSendThread::traverseTreeAndBuildNextPacketPayload(params);
#endif // SEND_SORTED_ENTITIES
}

View file

@ -39,11 +39,17 @@ private:
bool addDescendantsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData);
void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset);
bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params) override;
DiffTraversal _traversal;
EntityPriorityQueue _sendQueue;
std::unordered_set<EntityItemPointer> _entitiesToSend;
ConicalView _conicalView; // cached optimized view for fast priority calculations
// packet construction stuff
EntityTreeElementExtraEncodeDataPointer _extraEncodeData { new EntityTreeElementExtraEncodeData() };
int32_t _numEntitiesOffset { 0 };
uint16_t _numEntities { 0 };
};
#endif // hifi_EntityTreeSendThread_h

View file

@ -89,22 +89,15 @@ void DiffTraversal::Waypoint::getNextVisibleElementRepeat(
next.intersection = ViewFrustum::OUTSIDE;
}
DiffTraversal::DiffTraversal() {
const int32_t MIN_PATH_DEPTH = 16;
_path.reserve(MIN_PATH_DEPTH);
}
void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::VisibleElement& next,
const DiffTraversal::View& view, const DiffTraversal::View& lastView) {
if (_nextIndex == -1) {
// root case is special
++_nextIndex;
EntityTreeElementPointer element = _weakElement.lock();
if (element->getLastChangedContent() > lastView.startTime) {
next.element = element;
next.intersection = ViewFrustum::INTERSECT;
return;
}
next.element = element;
next.intersection = ViewFrustum::INTERSECT;
return;
}
if (_nextIndex < NUMBER_OF_CHILDREN) {
EntityTreeElementPointer element = _weakElement.lock();
@ -149,6 +142,11 @@ void DiffTraversal::Waypoint::getNextVisibleElementDifferential(DiffTraversal::V
next.intersection = ViewFrustum::OUTSIDE;
}
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) {
assert(root);
@ -246,7 +244,7 @@ std::ostream& operator<<(std::ostream& s, const DiffTraversal& traversal) {
for (size_t i = 0; i < traversal._path.size(); ++i) {
s << (int32_t)(traversal._path[i].getNextIndex());
if (i < traversal._path.size() - 1) {
s << "-->";
s << ":";
}
}
return s;

View file

@ -66,6 +66,8 @@ public:
float getCurrentRootSizeScale() const { return _currentView.rootSizeScale; }
float getCompletedRootSizeScale() const { return _completedView.rootSizeScale; }
float getCurrentLODOffset() const { return _currentView.lodLevelOffset; }
float getCompletedLODOffset() const { return _completedView.lodLevelOffset; }
uint64_t getStartOfCompletedTraversal() const { return _completedView.startTime; }
bool finished() const { return _path.empty(); }