History

add basics for send queue and tree traversal

Andrew Meadows committed 9 years ago

Commit 7edd99c1 parent 3ae5c213 files · +335 −4Browse files

Showing the changes to assignment-client/src/entities/EntityTreeSendThread.cpp (1 of 3 files). Show all

Unified · Split

assignment-client/src/entities/EntityTreeSendThread.cpp+261−0
@@ -10,12 +10,214 @@ · 9 unmodified lines
1010 //
1111
1212 #include "EntityTreeSendThread.h"
13+#include <iostream> // adebug
1314
1415 #include <EntityNodeData.h>
1516 #include <EntityTypes.h>
1617
1718 #include "EntityServer.h"
1819
20+const float INVALID_ENTITY_SEND_PRIORITY = -1.0e-6f;
21+
22+void PrioritizedEntity::updatePriority(const ViewFrustum& view) {
23+ EntityItemPointer entity = _weakEntity.lock();
24+ if (entity) {
25+ bool success;
26+ AACube cube = entity->getQueryAACube(success);
27+ if (success) {
28+ glm::vec3 center = cube.calcCenter() - view.getPosition();
29+ const float MIN_DISTANCE = 0.001f;
30+ float distanceToCenter = glm::length(center) + MIN_DISTANCE;
31+ float distance = distanceToCenter; //- 0.5f * cube.getScale();
32+ if (distance < MIN_DISTANCE) {
33+ // this object's bounding box overlaps the camera --> give it a big priority
34+ _priority = cube.getScale();
35+ } else {
36+ // NOTE: we assume view.aspectRatio < 1.0 (view width greater than height)
37+ // so we only check against the larger (horizontal) view angle
38+ float front = glm::dot(center, view.getDirection()) / distanceToCenter;
39+ if (front > cosf(view.getFieldOfView()) || distance < view.getCenterRadius()) {
40+ _priority = cube.getScale() / distance; // + front;
41+ } else {
42+ _priority = INVALID_ENTITY_SEND_PRIORITY;
43+ }
44+ }
45+ } else {
46+ // when in doubt just it something positive
47+ _priority = 1.0f;
48+ }
49+ } else {
50+ _priority = INVALID_ENTITY_SEND_PRIORITY;
51+ }
52+}
53+
54+TreeTraversalPath::Fork::Fork(EntityTreeElementPointer& element) : _nextIndex(0) {
55+ assert(element);
56+ _weakElement = element;
57+}
58+
59+EntityTreeElementPointer TreeTraversalPath::Fork::getNextElement(const ViewFrustum& view) {
60+ if (_nextIndex == -1) {
61+ // only get here for the TreeTraversalPath's root Fork at the very beginning of traversal
62+ // safe to assume this element is in view
63+ ++_nextIndex;
64+ return _weakElement.lock();
65+ } else if (_nextIndex < NUMBER_OF_CHILDREN) {
66+ EntityTreeElementPointer element = _weakElement.lock();
67+ if (element) {
68+ while (_nextIndex < NUMBER_OF_CHILDREN) {
69+ EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex);
70+ ++_nextIndex;
71+ if (nextElement && ViewFrustum::OUTSIDE != nextElement->computeViewIntersection(view)) {
72+ return nextElement;
73+ }
74+ }
75+ }
76+ }
77+ return EntityTreeElementPointer();
78+}
79+
80+EntityTreeElementPointer TreeTraversalPath::Fork::getNextElementAgain(const ViewFrustum& view, uint64_t oldTime) {
81+ if (_nextIndex == -1) {
82+ // only get here for the TreeTraversalPath's root Fork at the very beginning of traversal
83+ // safe to assume this element is in view
84+ ++_nextIndex;
85+ EntityTreeElementPointer element = _weakElement.lock();
86+ assert(element); // should never lose root element
87+ if (element->getLastChanged() < oldTime) {
88+ _nextIndex = NUMBER_OF_CHILDREN;
89+ return EntityTreeElementPointer();
90+ }
91+ if (element->getLastChanged() > oldTime) {
92+ return element;
93+ }
94+ }
95+ if (_nextIndex < NUMBER_OF_CHILDREN) {
96+ EntityTreeElementPointer element = _weakElement.lock();
97+ if (element) {
98+ while (_nextIndex < NUMBER_OF_CHILDREN) {
99+ EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex);
100+ ++_nextIndex;
101+ if (nextElement && nextElement->getLastChanged() > oldTime &&
102+ ViewFrustum::OUTSIDE != nextElement->computeViewIntersection(view)) {
103+ return nextElement;
104+ }
105+ }
106+ }
107+ }
108+ return EntityTreeElementPointer();
109+}
110+
111+EntityTreeElementPointer TreeTraversalPath::Fork::getNextElementDelta(const ViewFrustum& newView, const ViewFrustum& oldView, uint64_t oldTime) {
112+ if (_nextIndex == -1) {
113+ // only get here for the TreeTraversalPath's root Fork at the very beginning of traversal
114+ // safe to assume this element is in newView
115+ ++_nextIndex;
116+ EntityTreeElementPointer element = _weakElement.lock();
117+ assert(element); // should never lose root element
118+ if (element->getLastChanged() < oldTime) {
119+ _nextIndex = NUMBER_OF_CHILDREN;
120+ return EntityTreeElementPointer();
121+ }
122+ return element;
123+ } else if (_nextIndex < NUMBER_OF_CHILDREN) {
124+ EntityTreeElementPointer element = _weakElement.lock();
125+ if (element) {
126+ while (_nextIndex < NUMBER_OF_CHILDREN) {
127+ EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex);
128+ ++_nextIndex;
129+ if (nextElement &&
130+ !(nextElement->getLastChanged() < oldTime &&
131+ ViewFrustum::INSIDE == nextElement->computeViewIntersection(oldView)) &&
132+ ViewFrustum::OUTSIDE != nextElement->computeViewIntersection(newView)) {
133+ return nextElement;
134+ }
135+ }
136+ }
137+ }
138+ return EntityTreeElementPointer();
139+}
140+
141+TreeTraversalPath::TreeTraversalPath() {
142+ const int32_t MIN_PATH_DEPTH = 16;
143+ _forks.reserve(MIN_PATH_DEPTH);
144+ _traversalCallback = std::bind(&TreeTraversalPath::traverseFirstTime, this);
145+}
146+
147+void TreeTraversalPath::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root) {
148+ if (_startOfLastCompletedTraversal == 0) {
149+ _traversalCallback = std::bind(&TreeTraversalPath::traverseFirstTime, this);
150+ _currentView = view;
151+ } else if (_currentView.isVerySimilar(view)) {
152+ _traversalCallback = std::bind(&TreeTraversalPath::traverseAgain, this);
153+ } else {
154+ _currentView = view;
155+ _traversalCallback = std::bind(&TreeTraversalPath::traverseDelta, this);
156+ }
157+ _forks.clear();
158+ if (root) {
159+ _forks.push_back(Fork(root));
160+ // set root fork's index such that root element returned at getNextElement()
161+ _forks.back().initRootNextIndex();
162+ }
163+ _startOfCurrentTraversal = usecTimestampNow();
164+}
165+
166+EntityTreeElementPointer TreeTraversalPath::traverseFirstTime() {
167+ return _forks.back().getNextElement(_currentView);
168+}
169+
170+EntityTreeElementPointer TreeTraversalPath::traverseAgain() {
171+ return _forks.back().getNextElementAgain(_currentView, _startOfLastCompletedTraversal);
172+}
173+
174+EntityTreeElementPointer TreeTraversalPath::traverseDelta() {
175+ return _forks.back().getNextElementDelta(_currentView, _lastCompletedView, _startOfLastCompletedTraversal);
176+}
177+
178+EntityTreeElementPointer TreeTraversalPath::getNextElement() {
179+ if (_forks.empty() || !_traversalCallback) {
180+ return EntityTreeElementPointer();
181+ }
182+ EntityTreeElementPointer nextElement = _traversalCallback();
183+ if (nextElement) {
184+ int8_t nextIndex = _forks.back().getNextIndex();
185+ if (nextIndex > 0) {
186+ // nextElement needs to be added to the path
187+ _forks.push_back(Fork(nextElement));
188+ }
189+ } else {
190+ // we're done at this level
191+ while (!nextElement) {
192+ // pop one level
193+ _forks.pop_back();
194+ if (_forks.empty()) {
195+ // we've traversed the entire tree
196+ onCompleteTraversal();
197+ return nextElement;
198+ }
199+ // keep looking for nextElement
200+ nextElement = _traversalCallback();
201+ if (nextElement) {
202+ // we've descended one level so add it to the path
203+ _forks.push_back(Fork(nextElement));
204+ }
205+ }
206+ }
207+ return nextElement;
208+}
209+
210+void TreeTraversalPath::dump() const {
211+ for (size_t i = 0; i < _forks.size(); ++i) {
212+ std::cout << (int)(_forks[i].getNextIndex()) << "-->";
213+ }
214+}
215+
216+void TreeTraversalPath::onCompleteTraversal() {
217+ _lastCompletedView = _currentView;
218+ _startOfLastCompletedTraversal = _startOfCurrentTraversal;
219+}
220+
19221 void EntityTreeSendThread::preDistributionProcessing() {
20222 auto node = _node.toStrongRef();
21223 auto nodeData = static_cast<EntityNodeData*>(node->getLinkedData());
@@ -80,8 +282,67 @@ void EntityTreeSendThread::preDistributionProcessing() { · 58 unmodified lines
80282 }
81283 }
82284
285+static size_t adebug = 0;
286+
83287 void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,
84288 bool viewFrustumChanged, bool isFullScene) {
289+ if (viewFrustumChanged) {
290+ ViewFrustum view;
291+ nodeData->copyCurrentViewFrustum(view);
292+ EntityTreeElementPointer root = std::dynamic_pointer_cast<EntityTreeElement>(_myServer->getOctree()->getRoot());
293+ _path.startNewTraversal(view, root);
294+
295+ std::cout << "adebug reset view" << std::endl; // adebug
296+ adebug = 0;
297+ }
298+ if (!_path.empty()) {
299+ int32_t numElements = 0;
300+ uint64_t t0 = usecTimestampNow();
301+ uint64_t now = t0;
302+
303+ QVector<EntityItemPointer> entities;
304+ EntityTreeElementPointer nextElement = _path.getNextElement();
305+ while (nextElement) {
306+ nextElement->getEntities(_path.getView(), entities);
307+ ++numElements;
308+
309+ now = usecTimestampNow();
310+ const uint64_t PARTIAL_TRAVERSAL_TIME_BUDGET = 80;
311+ if (now - t0 > PARTIAL_TRAVERSAL_TIME_BUDGET) {
312+ break;
313+ }
314+ nextElement = _path.getNextElement();
315+ }
316+ uint64_t dt1 = now - t0;
317+ for (EntityItemPointer& entity : entities) {
318+ PrioritizedEntity entry(entity);
319+ entry.updatePriority(_path.getView());
320+ if (entry.getPriority() > INVALID_ENTITY_SEND_PRIORITY) {
321+ _sendQueue.push(entry);
322+ }
323+ }
324+ adebug += entities.size();
325+ std::cout << "adebug traverseTreeAndSendContents totalEntities = " << adebug
326+ << " numElements = " << numElements
327+ << " numEntities = " << entities.size()
328+ << " dt = " << dt1 << std::endl; // adebug
329+ } else if (!_sendQueue.empty()) {
330+
331+ while (!_sendQueue.empty()) {
332+ PrioritizedEntity entry = _sendQueue.top();
333+ EntityItemPointer entity = entry.getEntity();
334+ if (entity) {
335+ std::cout << "adebug traverseTreeAndSendContents() " << entry.getPriority()
336+ << " '" << entity->getName().toStdString() << "'"
337+ << std::endl; // adebug
338+ }
339+ _sendQueue.pop();
340+ }
341+ // std::priority_queue doesn't have a clear method,
342+ // so we "clear" _sendQueue by setting it equal to an empty queue
343+ _sendQueue = EntityPriorityQueue();
344+ }
345+
85346 OctreeSendThread::traverseTreeAndSendContents(node, nodeData, viewFrustumChanged, isFullScene);
86347 }
87348