mirror of
https://github.com/overte-org/overte.git
synced 2025-04-24 20:34:20 +02:00
split EntityPriorityQueue stuff into separate file
This commit is contained in:
parent
64cd209835
commit
abf968aab6
4 changed files with 262 additions and 230 deletions
170
assignment-client/src/entities/EntityPriorityQueue.cpp
Normal file
170
assignment-client/src/entities/EntityPriorityQueue.cpp
Normal file
|
@ -0,0 +1,170 @@
|
|||
//
|
||||
// EntityPriorityQueue.cpp
|
||||
// assignment-client/src/entities
|
||||
//
|
||||
// Created by Andrew Meadows 2017.08.08
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "EntityPriorityQueue.h"
|
||||
|
||||
const float DO_NOT_SEND = -1.0e-6f;
|
||||
|
||||
void ConicalView::set(const ViewFrustum& viewFrustum) {
|
||||
// The ConicalView has two parts: a central sphere (same as ViewFrustm) and a circular cone that bounds the frustum part.
|
||||
// Why? Because approximate intersection tests are much faster to compute for a cone than for a frustum.
|
||||
_position = viewFrustum.getPosition();
|
||||
_direction = viewFrustum.getDirection();
|
||||
|
||||
// We cache the sin and cos of the half angle of the cone that bounds the frustum.
|
||||
// (the math here is left as an exercise for the reader)
|
||||
float A = viewFrustum.getAspectRatio();
|
||||
float t = tanf(0.5f * viewFrustum.getFieldOfView());
|
||||
_cosAngle = 1.0f / sqrtf(1.0f + (A * A + 1.0f) * (t * t));
|
||||
_sinAngle = sqrtf(1.0f - _cosAngle * _cosAngle);
|
||||
|
||||
_radius = viewFrustum.getCenterRadius();
|
||||
}
|
||||
|
||||
float ConicalView::computePriority(const AACube& cube) const {
|
||||
glm::vec3 p = cube.calcCenter() - _position; // position of bounding sphere in view-frame
|
||||
float d = glm::length(p); // distance to center of bounding sphere
|
||||
float r = 0.5f * cube.getScale(); // radius of bounding sphere
|
||||
if (d < _radius + r) {
|
||||
return r;
|
||||
}
|
||||
if (glm::dot(p, _direction) > sqrtf(d * d - r * r) * _cosAngle - r * _sinAngle) {
|
||||
const float AVOID_DIVIDE_BY_ZERO = 0.001f;
|
||||
return r / (d + AVOID_DIVIDE_BY_ZERO);
|
||||
}
|
||||
return DO_NOT_SEND;
|
||||
}
|
||||
|
||||
// static
|
||||
float ConicalView::computePriority(const EntityItemPointer& entity) const {
|
||||
assert(entity);
|
||||
bool success;
|
||||
AACube cube = entity->getQueryAACube(success);
|
||||
if (success) {
|
||||
return computePriority(cube);
|
||||
} else {
|
||||
// when in doubt give it something positive
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
float PrioritizedEntity::updatePriority(const ConicalView& conicalView) {
|
||||
EntityItemPointer entity = _weakEntity.lock();
|
||||
if (entity) {
|
||||
_priority = conicalView.computePriority(entity);
|
||||
} else {
|
||||
_priority = DO_NOT_SEND;
|
||||
}
|
||||
return _priority;
|
||||
}
|
||||
|
||||
TraversalWaypoint::TraversalWaypoint(EntityTreeElementPointer& element) : _nextIndex(0) {
|
||||
assert(element);
|
||||
_weakElement = element;
|
||||
}
|
||||
|
||||
void TraversalWaypoint::getNextVisibleElementFirstTime(VisibleElement& next, const ViewFrustum& view) {
|
||||
// NOTE: no need to set next.intersection in the "FirstTime" context
|
||||
if (_nextIndex == -1) {
|
||||
// only get here for the root TraversalWaypoint at the very beginning of traversal
|
||||
// safe to assume this element intersects view
|
||||
++_nextIndex;
|
||||
next.element = _weakElement.lock();
|
||||
return;
|
||||
} else if (_nextIndex < NUMBER_OF_CHILDREN) {
|
||||
EntityTreeElementPointer element = _weakElement.lock();
|
||||
if (element) {
|
||||
while (_nextIndex < NUMBER_OF_CHILDREN) {
|
||||
EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex);
|
||||
++_nextIndex;
|
||||
if (nextElement && view.cubeIntersectsKeyhole(nextElement->getAACube())) {
|
||||
next.element = nextElement;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
next.element.reset();
|
||||
}
|
||||
|
||||
void TraversalWaypoint::getNextVisibleElementAgain(VisibleElement& next, const ViewFrustum& view, uint64_t lastTime) {
|
||||
if (_nextIndex == -1) {
|
||||
// only get here for the root TraversalWaypoint at the very beginning of traversal
|
||||
// safe to assume this element intersects view
|
||||
++_nextIndex;
|
||||
EntityTreeElementPointer element = _weakElement.lock();
|
||||
// root case is special: its intersection is always INTERSECT
|
||||
// and we can skip it if the content hasn't changed
|
||||
if (element->getLastChangedContent() > lastTime) {
|
||||
next.element = element;
|
||||
next.intersection = ViewFrustum::INTERSECT;
|
||||
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) {
|
||||
ViewFrustum::intersection intersection = view.calculateCubeKeyholeIntersection(nextElement->getAACube());
|
||||
if (intersection != ViewFrustum::OUTSIDE) {
|
||||
next.element = nextElement;
|
||||
next.intersection = intersection;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
next.element.reset();
|
||||
next.intersection = ViewFrustum::OUTSIDE;
|
||||
}
|
||||
|
||||
void TraversalWaypoint::getNextVisibleElementDifferential(VisibleElement& next,
|
||||
const ViewFrustum& view, const ViewFrustum& lastView, uint64_t lastTime) {
|
||||
if (_nextIndex == -1) {
|
||||
// only get here for the root TraversalWaypoint at the very beginning of traversal
|
||||
// safe to assume this element intersects view
|
||||
++_nextIndex;
|
||||
EntityTreeElementPointer element = _weakElement.lock();
|
||||
// root case is special: its intersection is always INTERSECT
|
||||
// and we can skip it if the content hasn't changed
|
||||
if (element->getLastChangedContent() > lastTime) {
|
||||
next.element = element;
|
||||
next.intersection = ViewFrustum::INTERSECT;
|
||||
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) {
|
||||
AACube cube = nextElement->getAACube();
|
||||
// NOTE: for differential case next.intersection is against the _completedView
|
||||
ViewFrustum::intersection intersection = lastView.calculateCubeKeyholeIntersection(cube);
|
||||
if ( lastView.calculateCubeKeyholeIntersection(cube) != ViewFrustum::OUTSIDE &&
|
||||
!(intersection == ViewFrustum::INSIDE && nextElement->getLastChanged() < lastTime)) {
|
||||
next.element = nextElement;
|
||||
next.intersection = intersection;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
next.element.reset();
|
||||
next.intersection = ViewFrustum::OUTSIDE;
|
||||
}
|
86
assignment-client/src/entities/EntityPriorityQueue.h
Normal file
86
assignment-client/src/entities/EntityPriorityQueue.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
//
|
||||
// EntityPriorityQueue.h
|
||||
// assignment-client/src/entities
|
||||
//
|
||||
// Created by Andrew Meadows 2017.08.08
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_EntityPriorityQueue_h
|
||||
#define hifi_EntityPriorityQueue_h
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include <AACube.h>
|
||||
|
||||
#include "EntityTreeElement.h"
|
||||
|
||||
const float SQRT_TWO_OVER_TWO = 0.7071067811865;
|
||||
const float DEFAULT_VIEW_RADIUS = 10.0f;
|
||||
|
||||
// ConicalView is an approximation of a ViewFrustum for fast calculation of sort priority.
|
||||
class ConicalView {
|
||||
public:
|
||||
ConicalView() {}
|
||||
ConicalView(const ViewFrustum& viewFrustum) { set(viewFrustum); }
|
||||
void set(const ViewFrustum& viewFrustum);
|
||||
float computePriority(const AACube& cube) const;
|
||||
float computePriority(const EntityItemPointer& entity) const;
|
||||
private:
|
||||
glm::vec3 _position { 0.0f, 0.0f, 0.0f };
|
||||
glm::vec3 _direction { 0.0f, 0.0f, 1.0f };
|
||||
float _sinAngle { SQRT_TWO_OVER_TWO };
|
||||
float _cosAngle { SQRT_TWO_OVER_TWO };
|
||||
float _radius { DEFAULT_VIEW_RADIUS };
|
||||
};
|
||||
|
||||
// PrioritizedEntity is a placeholder in a sorted queue.
|
||||
class PrioritizedEntity {
|
||||
public:
|
||||
PrioritizedEntity(EntityItemPointer entity, float priority) : _weakEntity(entity), _priority(priority) { }
|
||||
float updatePriority(const ConicalView& view);
|
||||
EntityItemPointer getEntity() const { return _weakEntity.lock(); }
|
||||
float getPriority() const { return _priority; }
|
||||
|
||||
class Compare {
|
||||
public:
|
||||
bool operator() (const PrioritizedEntity& A, const PrioritizedEntity& B) { return A._priority < B._priority; }
|
||||
};
|
||||
friend class Compare;
|
||||
|
||||
private:
|
||||
EntityItemWeakPointer _weakEntity;
|
||||
float _priority;
|
||||
};
|
||||
|
||||
// VisibleElement is a struct identifying an element and how it intersected the view.
|
||||
// The intersection is used to optimize culling entities from the sendQueue.
|
||||
class VisibleElement {
|
||||
public:
|
||||
EntityTreeElementPointer element;
|
||||
ViewFrustum::intersection intersection { ViewFrustum::OUTSIDE };
|
||||
};
|
||||
|
||||
// TraversalWaypoint is an bookmark in a "path" of waypoints during a traversal.
|
||||
class TraversalWaypoint {
|
||||
public:
|
||||
TraversalWaypoint(EntityTreeElementPointer& element);
|
||||
|
||||
void getNextVisibleElementFirstTime(VisibleElement& next, const ViewFrustum& view);
|
||||
void getNextVisibleElementAgain(VisibleElement& next, const ViewFrustum& view, uint64_t lastTime);
|
||||
void getNextVisibleElementDifferential(VisibleElement& next, const ViewFrustum& view, const ViewFrustum& lastView, uint64_t lastTime);
|
||||
|
||||
int8_t getNextIndex() const { return _nextIndex; }
|
||||
void initRootNextIndex() { _nextIndex = -1; }
|
||||
|
||||
protected:
|
||||
EntityTreeElementWeakPointer _weakElement;
|
||||
int8_t _nextIndex;
|
||||
};
|
||||
|
||||
using EntityPriorityQueue = std::priority_queue< PrioritizedEntity, std::vector<PrioritizedEntity>, PrioritizedEntity::Compare >;
|
||||
|
||||
#endif // hifi_EntityPriorityQueue_h
|
|
@ -17,165 +17,6 @@
|
|||
|
||||
#include "EntityServer.h"
|
||||
|
||||
const float DO_NOT_SEND = -1.0e-6f;
|
||||
|
||||
void ConicalView::set(const ViewFrustum& viewFrustum) {
|
||||
// The ConicalView has two parts: a central sphere (same as ViewFrustm) and a circular cone that bounds the frustum part.
|
||||
// Why? Because approximate intersection tests are much faster to compute for a cone than for a frustum.
|
||||
_position = viewFrustum.getPosition();
|
||||
_direction = viewFrustum.getDirection();
|
||||
|
||||
// We cache the sin and cos of the half angle of the cone that bounds the frustum.
|
||||
// (the math here is left as an exercise for the reader)
|
||||
float A = viewFrustum.getAspectRatio();
|
||||
float t = tanf(0.5f * viewFrustum.getFieldOfView());
|
||||
_cosAngle = 1.0f / sqrtf(1.0f + (A * A + 1.0f) * (t * t));
|
||||
_sinAngle = sqrtf(1.0f - _cosAngle * _cosAngle);
|
||||
|
||||
_radius = viewFrustum.getCenterRadius();
|
||||
}
|
||||
|
||||
float ConicalView::computePriority(const AACube& cube) const {
|
||||
glm::vec3 p = cube.calcCenter() - _position; // position of bounding sphere in view-frame
|
||||
float d = glm::length(p); // distance to center of bounding sphere
|
||||
float r = 0.5f * cube.getScale(); // radius of bounding sphere
|
||||
if (d < _radius + r) {
|
||||
return r;
|
||||
}
|
||||
if (glm::dot(p, _direction) > sqrtf(d * d - r * r) * _cosAngle - r * _sinAngle) {
|
||||
const float AVOID_DIVIDE_BY_ZERO = 0.001f;
|
||||
return r / (d + AVOID_DIVIDE_BY_ZERO);
|
||||
}
|
||||
return DO_NOT_SEND;
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
float ConicalView::computePriority(const EntityItemPointer& entity) const {
|
||||
assert(entity);
|
||||
bool success;
|
||||
AACube cube = entity->getQueryAACube(success);
|
||||
if (success) {
|
||||
return computePriority(cube);
|
||||
} else {
|
||||
// when in doubt give it something positive
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
float PrioritizedEntity::updatePriority(const ConicalView& conicalView) {
|
||||
EntityItemPointer entity = _weakEntity.lock();
|
||||
if (entity) {
|
||||
_priority = conicalView.computePriority(entity);
|
||||
} else {
|
||||
_priority = DO_NOT_SEND;
|
||||
}
|
||||
return _priority;
|
||||
}
|
||||
|
||||
Fork::Fork(EntityTreeElementPointer& element) : _nextIndex(0) {
|
||||
assert(element);
|
||||
_weakElement = element;
|
||||
}
|
||||
|
||||
void Fork::getNextVisibleElementFirstTime(VisibleElement& next, const ViewFrustum& view) {
|
||||
// NOTE: no need to set next.intersection in the "FirstTime" context
|
||||
if (_nextIndex == -1) {
|
||||
// only get here for the root Fork at the very beginning of traversal
|
||||
// safe to assume this element intersects view
|
||||
++_nextIndex;
|
||||
next.element = _weakElement.lock();
|
||||
return;
|
||||
} else if (_nextIndex < NUMBER_OF_CHILDREN) {
|
||||
EntityTreeElementPointer element = _weakElement.lock();
|
||||
if (element) {
|
||||
while (_nextIndex < NUMBER_OF_CHILDREN) {
|
||||
EntityTreeElementPointer nextElement = element->getChildAtIndex(_nextIndex);
|
||||
++_nextIndex;
|
||||
if (nextElement && view.cubeIntersectsKeyhole(nextElement->getAACube())) {
|
||||
next.element = nextElement;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
next.element.reset();
|
||||
}
|
||||
|
||||
void Fork::getNextVisibleElementAgain(VisibleElement& next, const ViewFrustum& view, uint64_t lastTime) {
|
||||
if (_nextIndex == -1) {
|
||||
// only get here for the root Fork at the very beginning of traversal
|
||||
// safe to assume this element intersects view
|
||||
++_nextIndex;
|
||||
EntityTreeElementPointer element = _weakElement.lock();
|
||||
// root case is special: its intersection is always INTERSECT
|
||||
// and we can skip it if the content hasn't changed
|
||||
if (element->getLastChangedContent() > lastTime) {
|
||||
next.element = element;
|
||||
next.intersection = ViewFrustum::INTERSECT;
|
||||
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) {
|
||||
ViewFrustum::intersection intersection = view.calculateCubeKeyholeIntersection(nextElement->getAACube());
|
||||
if (intersection != ViewFrustum::OUTSIDE) {
|
||||
next.element = nextElement;
|
||||
next.intersection = intersection;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
next.element.reset();
|
||||
next.intersection = ViewFrustum::OUTSIDE;
|
||||
}
|
||||
|
||||
void Fork::getNextVisibleElementDifferential(VisibleElement& next,
|
||||
const ViewFrustum& view, const ViewFrustum& lastView, uint64_t lastTime) {
|
||||
if (_nextIndex == -1) {
|
||||
// only get here for the root Fork at the very beginning of traversal
|
||||
// safe to assume this element intersects view
|
||||
++_nextIndex;
|
||||
EntityTreeElementPointer element = _weakElement.lock();
|
||||
// root case is special: its intersection is always INTERSECT
|
||||
// and we can skip it if the content hasn't changed
|
||||
if (element->getLastChangedContent() > lastTime) {
|
||||
next.element = element;
|
||||
next.intersection = ViewFrustum::INTERSECT;
|
||||
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) {
|
||||
AACube cube = nextElement->getAACube();
|
||||
// NOTE: for differential case next.intersection is against the _completedView
|
||||
ViewFrustum::intersection intersection = lastView.calculateCubeKeyholeIntersection(cube);
|
||||
if ( lastView.calculateCubeKeyholeIntersection(cube) != ViewFrustum::OUTSIDE &&
|
||||
!(intersection == ViewFrustum::INSIDE && nextElement->getLastChanged() < lastTime)) {
|
||||
next.element = nextElement;
|
||||
next.intersection = intersection;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
next.element.reset();
|
||||
next.intersection = ViewFrustum::OUTSIDE;
|
||||
}
|
||||
|
||||
EntityTreeSendThread::EntityTreeSendThread(OctreeServer* myServer, const SharedNodePointer& node)
|
||||
: OctreeSendThread(myServer, node) {
|
||||
const int32_t MIN_PATH_DEPTH = 16;
|
||||
|
@ -454,7 +295,7 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& viewFrustum, Ent
|
|||
|
||||
_traversalPath.clear();
|
||||
assert(root);
|
||||
_traversalPath.push_back(Fork(root));
|
||||
_traversalPath.push_back(TraversalWaypoint(root));
|
||||
// set root fork's index such that root element returned at getNextElement()
|
||||
_traversalPath.back().initRootNextIndex();
|
||||
|
||||
|
@ -472,7 +313,7 @@ void EntityTreeSendThread::getNextVisibleElement(VisibleElement& next) {
|
|||
int8_t nextIndex = _traversalPath.back().getNextIndex();
|
||||
if (nextIndex > 0) {
|
||||
// next.element needs to be added to the path
|
||||
_traversalPath.push_back(Fork(next.element));
|
||||
_traversalPath.push_back(TraversalWaypoint(next.element));
|
||||
}
|
||||
} else {
|
||||
// we're done at this level
|
||||
|
@ -489,7 +330,7 @@ void EntityTreeSendThread::getNextVisibleElement(VisibleElement& next) {
|
|||
_getNextVisibleElementCallback(next);
|
||||
if (next.element) {
|
||||
// we've descended one level so add it to the path
|
||||
_traversalPath.push_back(Fork(next.element));
|
||||
_traversalPath.push_back(TraversalWaypoint(next.element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,80 +12,15 @@
|
|||
#ifndef hifi_EntityTreeSendThread_h
|
||||
#define hifi_EntityTreeSendThread_h
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include "../octree/OctreeSendThread.h"
|
||||
|
||||
#include <AACube.h>
|
||||
|
||||
#include "EntityTreeElement.h"
|
||||
|
||||
const float SQRT_TWO_OVER_TWO = 0.7071067811865;
|
||||
const float DEFAULT_VIEW_RADIUS = 10.0f;
|
||||
#include "EntityPriorityQueue.h"
|
||||
|
||||
class EntityNodeData;
|
||||
class EntityItem;
|
||||
|
||||
|
||||
class ConicalView {
|
||||
public:
|
||||
ConicalView() {}
|
||||
ConicalView(const ViewFrustum& viewFrustum) { set(viewFrustum); }
|
||||
void set(const ViewFrustum& viewFrustum);
|
||||
float computePriority(const AACube& cube) const;
|
||||
float computePriority(const EntityItemPointer& entity) const;
|
||||
private:
|
||||
glm::vec3 _position { 0.0f, 0.0f, 0.0f };
|
||||
glm::vec3 _direction { 0.0f, 0.0f, 1.0f };
|
||||
float _sinAngle { SQRT_TWO_OVER_TWO };
|
||||
float _cosAngle { SQRT_TWO_OVER_TWO };
|
||||
float _radius { DEFAULT_VIEW_RADIUS };
|
||||
};
|
||||
|
||||
class PrioritizedEntity {
|
||||
public:
|
||||
PrioritizedEntity(EntityItemPointer entity, float priority) : _weakEntity(entity), _priority(priority) { }
|
||||
float updatePriority(const ConicalView& view);
|
||||
EntityItemPointer getEntity() const { return _weakEntity.lock(); }
|
||||
float getPriority() const { return _priority; }
|
||||
|
||||
class Compare {
|
||||
public:
|
||||
bool operator() (const PrioritizedEntity& A, const PrioritizedEntity& B) { return A._priority < B._priority; }
|
||||
};
|
||||
friend class Compare;
|
||||
|
||||
private:
|
||||
EntityItemWeakPointer _weakEntity;
|
||||
float _priority;
|
||||
};
|
||||
|
||||
class VisibleElement {
|
||||
public:
|
||||
EntityTreeElementPointer element;
|
||||
ViewFrustum::intersection intersection { ViewFrustum::OUTSIDE };
|
||||
};
|
||||
|
||||
class Fork {
|
||||
public:
|
||||
Fork(EntityTreeElementPointer& element);
|
||||
|
||||
void getNextVisibleElementFirstTime(VisibleElement& next, const ViewFrustum& view);
|
||||
void getNextVisibleElementAgain(VisibleElement& next, const ViewFrustum& view, uint64_t lastTime);
|
||||
void getNextVisibleElementDifferential(VisibleElement& next, const ViewFrustum& view, const ViewFrustum& lastView, uint64_t lastTime);
|
||||
|
||||
int8_t getNextIndex() const { return _nextIndex; }
|
||||
void initRootNextIndex() { _nextIndex = -1; }
|
||||
|
||||
protected:
|
||||
EntityTreeElementWeakPointer _weakElement;
|
||||
int8_t _nextIndex;
|
||||
};
|
||||
|
||||
using EntityPriorityQueue = std::priority_queue< PrioritizedEntity, std::vector<PrioritizedEntity>, PrioritizedEntity::Compare >;
|
||||
|
||||
|
||||
class EntityTreeSendThread : public OctreeSendThread {
|
||||
|
||||
public:
|
||||
EntityTreeSendThread(OctreeServer* myServer, const SharedNodePointer& node);
|
||||
|
||||
|
@ -107,7 +42,7 @@ private:
|
|||
ViewFrustum _currentView;
|
||||
ViewFrustum _completedView;
|
||||
ConicalView _conicalView; // optimized view for fast priority calculations
|
||||
std::vector<Fork> _traversalPath;
|
||||
std::vector<TraversalWaypoint> _traversalPath;
|
||||
std::function<void (VisibleElement&)> _getNextVisibleElementCallback { nullptr };
|
||||
std::function<void (VisibleElement&)> _scanNextElementCallback { nullptr };
|
||||
uint64_t _startOfCompletedTraversal { 0 };
|
||||
|
|
Loading…
Reference in a new issue