give EntityTree a workload/Space instance

This commit is contained in:
Andrew Meadows 2018-02-15 12:57:58 -08:00
parent 1247f88d83
commit f35469c0de
15 changed files with 153 additions and 63 deletions

View file

@ -13,7 +13,7 @@ setup_memory_debugger()
link_hifi_libraries( link_hifi_libraries(
audio avatars octree gpu graphics fbx entities audio avatars octree gpu graphics fbx entities
networking animation recording shared script-engine embedded-webserver networking animation recording shared script-engine embedded-webserver
controllers physics plugins midi image controllers physics plugins midi image workload
) )
add_dependencies(${TARGET_NAME} oven) add_dependencies(${TARGET_NAME} oven)

View file

@ -14,5 +14,6 @@ include_hifi_library_headers(audio)
include_hifi_library_headers(entities) include_hifi_library_headers(entities)
include_hifi_library_headers(octree) include_hifi_library_headers(octree)
include_hifi_library_headers(task) include_hifi_library_headers(task)
include_hifi_library_headers(workload)
target_bullet() target_bullet()

View file

@ -14,6 +14,7 @@ include_hifi_library_headers(entities)
include_hifi_library_headers(avatars) include_hifi_library_headers(avatars)
include_hifi_library_headers(controllers) include_hifi_library_headers(controllers)
include_hifi_library_headers(task) include_hifi_library_headers(task)
include_hifi_library_headers(workload)
target_bullet() target_bullet()
target_polyvox() target_polyvox()

View file

@ -1,4 +1,4 @@
set(TARGET_NAME entities) set(TARGET_NAME entities)
setup_hifi_library(Network Script) setup_hifi_library(Network Script)
include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}")
link_hifi_libraries(shared networking octree avatars graphics) link_hifi_libraries(shared workload networking octree avatars graphics)

View file

@ -2365,12 +2365,14 @@ QList<EntityDynamicPointer> EntityItem::getActionsOfType(EntityDynamicType typeT
void EntityItem::locationChanged(bool tellPhysics) { void EntityItem::locationChanged(bool tellPhysics) {
requiresRecalcBoxes(); requiresRecalcBoxes();
if (tellPhysics) { EntityTreePointer tree = getTree();
_flags |= Simulation::DIRTY_TRANSFORM; if (tree) {
EntityTreePointer tree = getTree(); if (tellPhysics) {
if (tree) { _flags |= Simulation::DIRTY_TRANSFORM;
tree->entityChanged(getThisPointer()); tree->entityChanged(getThisPointer());
} }
glm::vec4 sphere(getWorldPosition(), 0.5f * glm::length(getScaledDimensions()));
tree->queueUpdateSpaceProxy(_spaceIndex, sphere);
} }
SpatiallyNestable::locationChanged(tellPhysics); // tell all the children, also SpatiallyNestable::locationChanged(tellPhysics); // tell all the children, also
somethingChangedNotification(); somethingChangedNotification();

View file

@ -477,6 +477,8 @@ public:
void setCauterized(bool value) { _cauterized = value; } void setCauterized(bool value) { _cauterized = value; }
bool getCauterized() const { return _cauterized; } bool getCauterized() const { return _cauterized; }
void setSpaceIndex(int32_t index) { assert(_spaceIndex == -1); _spaceIndex = index; }
int32_t getSpaceIndex() const { return _spaceIndex; }
signals: signals:
void requestRenderUpdate(); void requestRenderUpdate();
@ -630,6 +632,7 @@ protected:
quint64 _lastUpdatedAccelerationTimestamp { 0 }; quint64 _lastUpdatedAccelerationTimestamp { 0 };
quint64 _lastUpdatedQueryAACubeTimestamp { 0 }; quint64 _lastUpdatedQueryAACubeTimestamp { 0 };
int32_t _spaceIndex { -1 }; // index to proxy in workload::Space
bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera
}; };

View file

@ -560,37 +560,49 @@ void EntityTree::setSimulation(EntitySimulationPointer simulation) {
} }
void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ignoreWarnings) { void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ignoreWarnings) {
EntityTreeElementPointer containingElement = getContainingElement(entityID); EntityItemPointer entity;
if (!containingElement) { {
QReadLocker locker(&_entityMapLock);
entity = _entityMap.value(entityID);
}
if (!entity) {
if (!ignoreWarnings) { if (!ignoreWarnings) {
qCWarning(entities) << "EntityTree::deleteEntity() on non-existent entityID=" << entityID; qCWarning(entities) << "EntityTree::deleteEntity() on unknown entityID=" << entityID;
} }
return; return;
} }
if (entity->getLocked() && !force) {
EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID);
if (!existingEntity) {
if (!ignoreWarnings) {
qCWarning(entities) << "EntityTree::deleteEntity() on non-existant entity item with entityID=" << entityID;
}
return;
}
if (existingEntity->getLocked() && !force) {
if (!ignoreWarnings) { if (!ignoreWarnings) {
qCDebug(entities) << "ERROR! EntityTree::deleteEntity() trying to delete locked entity. entityID=" << entityID; qCDebug(entities) << "ERROR! EntityTree::deleteEntity() trying to delete locked entity. entityID=" << entityID;
} }
return; return;
} }
if (!ignoreWarnings) {
if (!entity->getElement()) {
qCWarning(entities) << "EntityTree::deleteEntity() found entity with entityID=" << entityID
<< " in map but it doesn't know its containing element";
} else {
// check for element mismatch
EntityItemPointer otherEntity = entity->getElement()->getEntityWithEntityItemID(entityID);
if (!otherEntity) {
qCWarning(entities) << "EntityTree::deleteEntity() on entity with entityID=" << entityID
<< " but the containing element of record cannot find it";
} else if (otherEntity != entity) {
qCWarning(entities) << "EntityTree::deleteEntity() on entity with entityID=" << entityID
<< " but the containing element of record found a different entity";
}
}
}
unhookChildAvatar(entityID); unhookChildAvatar(entityID);
emit deletingEntity(entityID); emit deletingEntity(entityID);
emit deletingEntityPointer(existingEntity.get()); emit deletingEntityPointer(entity.get());
// NOTE: callers must lock the tree before using this method // NOTE: callers must lock the tree before using this method
DeleteEntityOperator theOperator(getThisPointer(), entityID); DeleteEntityOperator theOperator(getThisPointer(), entityID);
existingEntity->forEachDescendant([&](SpatiallyNestablePointer descendant) { entity->forEachDescendant([&](SpatiallyNestablePointer descendant) {
auto descendantID = descendant->getID(); auto descendantID = descendant->getID();
theOperator.addEntityIDToDeleteList(descendantID); theOperator.addEntityIDToDeleteList(descendantID);
emit deletingEntity(descendantID); emit deletingEntity(descendantID);
@ -620,34 +632,46 @@ void EntityTree::deleteEntities(QSet<EntityItemID> entityIDs, bool force, bool i
// NOTE: callers must lock the tree before using this method // NOTE: callers must lock the tree before using this method
DeleteEntityOperator theOperator(getThisPointer()); DeleteEntityOperator theOperator(getThisPointer());
foreach(const EntityItemID& entityID, entityIDs) { foreach(const EntityItemID& entityID, entityIDs) {
EntityTreeElementPointer containingElement = getContainingElement(entityID); EntityItemPointer entity;
if (!containingElement) { {
QReadLocker locker(&_entityMapLock);
entity = _entityMap.value(entityID);
}
if (!entity) {
if (!ignoreWarnings) { if (!ignoreWarnings) {
qCWarning(entities) << "EntityTree::deleteEntities() on non-existent entityID=" << entityID; qCWarning(entities) << "EntityTree::deleteEntities() on unknown entityID=" << entityID;
} }
continue; continue;
} }
if (entity->getLocked() && !force) {
EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID);
if (!existingEntity) {
if (!ignoreWarnings) {
qCWarning(entities) << "EntityTree::deleteEntities() on non-existent entity item with entityID=" << entityID;
}
continue;
}
if (existingEntity->getLocked() && !force) {
if (!ignoreWarnings) { if (!ignoreWarnings) {
qCDebug(entities) << "ERROR! EntityTree::deleteEntities() trying to delete locked entity. entityID=" << entityID; qCDebug(entities) << "ERROR! EntityTree::deleteEntities() trying to delete locked entity. entityID=" << entityID;
} }
continue; continue;
} }
if (!ignoreWarnings) {
if (!entity->getElement()) {
qCWarning(entities) << "EntityTree::deleteEntities() found entity with entityID=" << entityID
<< " in map but it doesn't know its containing element";
} else {
// check for element mismatch
EntityItemPointer otherEntity = entity->getElement()->getEntityWithEntityItemID(entityID);
if (!otherEntity) {
qCWarning(entities) << "EntityTree::deleteEntities() on entity with entityID=" << entityID
<< " but the containing element of record cannot find it";
} else if (otherEntity != entity) {
qCWarning(entities) << "EntityTree::deleteEntities() on entity with entityID=" << entityID
<< " but the containing element of record found a different entity";
}
}
}
// tell our delete operator about this entityID // tell our delete operator about this entityID
unhookChildAvatar(entityID); unhookChildAvatar(entityID);
theOperator.addEntityIDToDeleteList(entityID); theOperator.addEntityIDToDeleteList(entityID);
emit deletingEntity(entityID); emit deletingEntity(entityID);
emit deletingEntityPointer(existingEntity.get()); emit deletingEntityPointer(entity.get());
} }
if (theOperator.getEntities().size() > 0) { if (theOperator.getEntities().size() > 0) {
@ -1209,6 +1233,10 @@ bool EntityTree::verifyNonce(const QString& certID, const QString& nonce, Entity
return verificationSuccess; return verificationSuccess;
} }
void EntityTree::queueUpdateSpaceProxy(int32_t index, const glm::vec4& sphere) {
_spaceUpdates.push_back(std::pair<int32_t, glm::vec4>(index, sphere));
}
void EntityTree::processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { void EntityTree::processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) {
int certIDByteArraySize; int certIDByteArraySize;
int textByteArraySize; int textByteArraySize;
@ -1810,6 +1838,12 @@ void EntityTree::update(bool simulate) {
} }
}); });
} }
// process Space queues
_space.deleteProxies(_spaceDeletes);
_spaceDeletes.clear();
_space.updateProxies(_spaceUpdates);
_spaceUpdates.clear();
} }
quint64 EntityTree::getAdjustedConsiderSince(quint64 sinceTime) { quint64 EntityTree::getAdjustedConsiderSince(quint64 sinceTime) {
@ -1979,11 +2013,25 @@ void EntityTree::addEntityMapEntry(EntityItemPointer entity) {
return; return;
} }
_entityMap.insert(id, entity); _entityMap.insert(id, entity);
// create a proxy for the entity in the workload/Space container
glm::vec4 sphere(entity->getWorldPosition(), 0.5f * glm::length(entity->getScaledDimensions()));
int32_t spaceIndex = _space.createProxy(sphere);
entity->setSpaceIndex(spaceIndex);
} }
void EntityTree::clearEntityMapEntry(const EntityItemID& id) { void EntityTree::clearEntityMapEntry(const EntityItemID& id) {
// this method only called by DeleteEntityOperator
QWriteLocker locker(&_entityMapLock); QWriteLocker locker(&_entityMapLock);
_entityMap.remove(id); QHash<EntityItemID, EntityItemPointer>::iterator itr = _entityMap.find(id);
if (itr != _entityMap.end()) {
// queue delete from _space BEFORE removing from map
int32_t spaceIndex = itr.value()->getSpaceIndex();
assert(spaceIndex != -1);
_spaceDeletes.push_back(spaceIndex);
_entityMap.erase(itr);
}
} }
void EntityTree::debugDumpMap() { void EntityTree::debugDumpMap() {

View file

@ -17,6 +17,7 @@
#include <Octree.h> #include <Octree.h>
#include <SpatialParentFinder.h> #include <SpatialParentFinder.h>
#include <workload/Space.h>
class EntityTree; class EntityTree;
using EntityTreePointer = std::shared_ptr<EntityTree>; using EntityTreePointer = std::shared_ptr<EntityTree>;
@ -280,6 +281,8 @@ public:
void setMyAvatar(std::shared_ptr<AvatarData> myAvatar) { _myAvatar = myAvatar; } void setMyAvatar(std::shared_ptr<AvatarData> myAvatar) { _myAvatar = myAvatar; }
void queueUpdateSpaceProxy(int32_t index, const glm::vec4& sphere);
signals: signals:
void deletingEntity(const EntityItemID& entityID); void deletingEntity(const EntityItemID& entityID);
void deletingEntityPointer(EntityItem* entityID); void deletingEntityPointer(EntityItem* entityID);
@ -387,6 +390,9 @@ private:
void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation); void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation);
std::shared_ptr<AvatarData> _myAvatar{ nullptr }; std::shared_ptr<AvatarData> _myAvatar{ nullptr };
workload::Space _space;
std::vector< std::pair<int32_t, glm::vec4> > _spaceUpdates;
std::vector< int32_t > _spaceDeletes;
}; };
#endif // hifi_EntityTree_h #endif // hifi_EntityTree_h

View file

@ -7,5 +7,6 @@ include_hifi_library_headers(avatars)
include_hifi_library_headers(audio) include_hifi_library_headers(audio)
include_hifi_library_headers(octree) include_hifi_library_headers(octree)
include_hifi_library_headers(animation) include_hifi_library_headers(animation)
include_hifi_library_headers(workload)
target_bullet() target_bullet()

View file

@ -20,3 +20,4 @@ endif ()
link_hifi_libraries(shared networking octree gpu procedural graphics model-networking ktx recording avatars fbx entities controllers animation audio physics image midi) link_hifi_libraries(shared networking octree gpu procedural graphics model-networking ktx recording avatars fbx entities controllers animation audio physics image midi)
# ui includes gl, but link_hifi_libraries does not use transitive includes, so gl must be explicit # ui includes gl, but link_hifi_libraries does not use transitive includes, so gl must be explicit
include_hifi_library_headers(gl) include_hifi_library_headers(gl)
include_hifi_library_headers(workload)

View file

@ -27,6 +27,7 @@
#include "VrMenu.h" #include "VrMenu.h"
#include "ui/Logging.h" #include "ui/Logging.h"
#include <iostream> // adebug
#include <PointerManager.h> #include <PointerManager.h>
@ -619,7 +620,13 @@ class KeyboardFocusHack : public QObject {
public: public:
KeyboardFocusHack() { KeyboardFocusHack() {
Q_ASSERT(_mainWindow); Q_ASSERT(_mainWindow);
std::cout << "adebug _mainWindow = " << (void*)(_mainWindow) << std::endl; // adebug
QTimer::singleShot(200, [=] { QTimer::singleShot(200, [=] {
_mainWindow = findMainWindow();
std::cout << "adebug again _mainWindow = " << (void*)(_mainWindow) << std::endl; // adebug
std::cout << "adebug _mainWindow->x() = " << _mainWindow->x() << std::endl;
std::cout << " adebug _mainWindow->y() = " << _mainWindow->y() << std::endl;
std::cout << std::endl; // adebug
_hackWindow = new QWindow(); _hackWindow = new QWindow();
_hackWindow->setFlags(Qt::FramelessWindowHint); _hackWindow->setFlags(Qt::FramelessWindowHint);
_hackWindow->setGeometry(_mainWindow->x(), _mainWindow->y(), 10, 10); _hackWindow->setGeometry(_mainWindow->x(), _mainWindow->y(), 10, 10);
@ -647,10 +654,11 @@ private:
break; break;
} }
} }
std::cout << "adebug findMainWindow() result = " << (void*)(result) << std::endl; // adebug
return result; return result;
} }
QWindow* const _mainWindow { findMainWindow() }; QWindow* _mainWindow { findMainWindow() };
QWindow* _hackWindow { nullptr }; QWindow* _hackWindow { nullptr };
}; };

View file

@ -34,38 +34,26 @@ int32_t Space::createProxy(const Space::Sphere& newSphere) {
} }
} }
void Space::deleteProxy(int32_t proxyId) { void Space::deleteProxies(const std::vector<int32_t>& deadIndices) {
if (proxyId >= (int32_t)_proxies.size() || _proxies.empty()) { for (uint32_t i = 0; i < deadIndices.size(); ++i) {
return; deleteProxy(deadIndices[i]);
}
if (proxyId == (int32_t)_proxies.size() - 1) {
// remove proxy on back
_proxies.pop_back();
if (!_freeIndices.empty()) {
// remove any freeIndices on back
std::sort(_freeIndices.begin(), _freeIndices.end());
while(!_freeIndices.empty() && _freeIndices.back() == (int32_t)_proxies.size() - 1) {
_freeIndices.pop_back();
_proxies.pop_back();
}
}
} else {
_proxies[proxyId].region = Space::REGION_INVALID;
_freeIndices.push_back(proxyId);
} }
} }
void Space::updateProxy(int32_t proxyId, const Space::Sphere& newSphere) { void Space::updateProxies(const std::vector<std::pair<int32_t, Sphere> >& changedProxies) {
if (proxyId >= (int32_t)_proxies.size()) { for (uint32_t i = 0; i < changedProxies.size(); ++i) {
return; int32_t proxyId = changedProxies[i].first;
if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) {
updateProxy(changedProxies[i].first, changedProxies[i].second);
}
} }
_proxies[proxyId].sphere = newSphere;
} }
void Space::setViews(const std::vector<Space::View>& views) { void Space::setViews(const std::vector<Space::View>& views) {
_views = views; _views = views;
} }
// TODO?: move this to an algorithm/job?
void Space::categorizeAndGetChanges(std::vector<Space::Change>& changes) { void Space::categorizeAndGetChanges(std::vector<Space::Change>& changes) {
uint32_t numProxies = (uint32_t)_proxies.size(); uint32_t numProxies = (uint32_t)_proxies.size();
uint32_t numViews = (uint32_t)_views.size(); uint32_t numViews = (uint32_t)_views.size();
@ -92,3 +80,31 @@ void Space::categorizeAndGetChanges(std::vector<Space::Change>& changes) {
} }
} }
// private
void Space::deleteProxy(int32_t proxyId) {
if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) {
if (proxyId == (int32_t)_proxies.size() - 1) {
// remove proxy on back
_proxies.pop_back();
if (!_freeIndices.empty()) {
// remove any freeIndices on back
std::sort(_freeIndices.begin(), _freeIndices.end());
while(!_freeIndices.empty() && _freeIndices.back() == (int32_t)_proxies.size() - 1) {
_freeIndices.pop_back();
_proxies.pop_back();
}
}
} else {
_proxies[proxyId].region = Space::REGION_INVALID;
_freeIndices.push_back(proxyId);
}
}
}
// private
void Space::updateProxy(int32_t proxyId, const Space::Sphere& newSphere) {
if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) {
_proxies[proxyId].sphere = newSphere;
}
}

View file

@ -60,8 +60,8 @@ public:
Space() {} Space() {}
int32_t createProxy(const Sphere& sphere); int32_t createProxy(const Sphere& sphere);
void deleteProxy(int32_t proxyId); void deleteProxies(const std::vector<int32_t>& deadIndices);
void updateProxy(int32_t proxyId, const Sphere& sphere); void updateProxies(const std::vector<std::pair<int32_t, Sphere> >& changedProxies);
void setViews(const std::vector<View>& views); void setViews(const std::vector<View>& views);
uint32_t getNumObjects() const { return (uint32_t)(_proxies.size() - _freeIndices.size()); } uint32_t getNumObjects() const { return (uint32_t)(_proxies.size() - _freeIndices.size()); }
@ -69,6 +69,9 @@ public:
void categorizeAndGetChanges(std::vector<Change>& changes); void categorizeAndGetChanges(std::vector<Change>& changes);
private: private:
void deleteProxy(int32_t proxyId);
void updateProxy(int32_t proxyId, const Sphere& sphere);
std::vector<Proxy> _proxies; std::vector<Proxy> _proxies;
std::vector<View> _views; std::vector<View> _views;
std::vector<int32_t> _freeIndices; std::vector<int32_t> _freeIndices;

View file

@ -7,7 +7,7 @@ setup_memory_debugger()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
# link in the shared libraries # link in the shared libraries
link_hifi_libraries(entities avatars shared octree gpu graphics fbx networking animation audio gl) link_hifi_libraries(entities avatars shared workload octree gpu graphics fbx networking animation audio gl)
if (WIN32) if (WIN32)
add_dependency_external_projects(wasapi) add_dependency_external_projects(wasapi)

View file

@ -18,7 +18,7 @@ link_hifi_libraries(
render render-utils render render-utils
graphics fbx model-networking graphics fbx model-networking
entities entities-renderer audio avatars script-engine entities entities-renderer audio avatars script-engine
physics procedural midi qml ui physics procedural midi qml ui workload
${PLATFORM_GL_BACKEND} ${PLATFORM_GL_BACKEND}
) )