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
10//10//
11 11
12#include "EntityTreeSendThread.h"12#include "EntityTreeSendThread.h"
13#include <iostream> // adebug
13 14
14#include <EntityNodeData.h>15#include <EntityNodeData.h>
15#include <EntityTypes.h>16#include <EntityTypes.h>
16 17
17#include "EntityServer.h"18#include "EntityServer.h"
18 19
20const float INVALID_ENTITY_SEND_PRIORITY = -1.0e-6f;
21
22void 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
54TreeTraversalPath::Fork::Fork(EntityTreeElementPointer& element) : _nextIndex(0) {
55 assert(element);
56 _weakElement = element;
57}
58
59EntityTreeElementPointer 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
80EntityTreeElementPointer 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
111EntityTreeElementPointer 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
141TreeTraversalPath::TreeTraversalPath() {
142 const int32_t MIN_PATH_DEPTH = 16;
143 _forks.reserve(MIN_PATH_DEPTH);
144 _traversalCallback = std::bind(&TreeTraversalPath::traverseFirstTime, this);
145}
146
147void 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
166EntityTreeElementPointer TreeTraversalPath::traverseFirstTime() {
167 return _forks.back().getNextElement(_currentView);
168}
169
170EntityTreeElementPointer TreeTraversalPath::traverseAgain() {
171 return _forks.back().getNextElementAgain(_currentView, _startOfLastCompletedTraversal);
172}
173
174EntityTreeElementPointer TreeTraversalPath::traverseDelta() {
175 return _forks.back().getNextElementDelta(_currentView, _lastCompletedView, _startOfLastCompletedTraversal);
176}
177
178EntityTreeElementPointer 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
210void TreeTraversalPath::dump() const {
211 for (size_t i = 0; i < _forks.size(); ++i) {
212 std::cout << (int)(_forks[i].getNextIndex()) << "-->";
213 }
214}
215
216void TreeTraversalPath::onCompleteTraversal() {
217 _lastCompletedView = _currentView;
218 _startOfLastCompletedTraversal = _startOfCurrentTraversal;
219}
220
19void EntityTreeSendThread::preDistributionProcessing() {221void EntityTreeSendThread::preDistributionProcessing() {
20 auto node = _node.toStrongRef();222 auto node = _node.toStrongRef();
21 auto nodeData = static_cast<EntityNodeData*>(node->getLinkedData());223 auto nodeData = static_cast<EntityNodeData*>(node->getLinkedData());
@@ -80,8 +282,67 @@ void EntityTreeSendThread::preDistributionProcessing() { · 58 unmodified lines
80 }282 }
81}283}
82 284
285static size_t adebug = 0;
286
83void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,287void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,
84 bool viewFrustumChanged, bool isFullScene) {288 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
85 OctreeSendThread::traverseTreeAndSendContents(node, nodeData, viewFrustumChanged, isFullScene);346 OctreeSendThread::traverseTreeAndSendContents(node, nodeData, viewFrustumChanged, isFullScene);
86}347}
87 348