maintain Space proxies for entities

This commit is contained in:
Andrew Meadows 2018-02-20 17:37:36 -08:00
parent 76d2e9bc78
commit e7495d830b
13 changed files with 75 additions and 25 deletions

View file

@ -35,6 +35,10 @@ void EntityTreeHeadlessViewer::update() {
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
tree->withTryWriteLock([&] {
tree->update();
// flush final EntityTree references to deleted entities
std::vector<EntityItemPointer> deletedEntities;
tree->swapRemovedEntities(deletedEntities);
});
}
}

View file

@ -4544,8 +4544,6 @@ void Application::init() {
_physicsEngine->init();
EntityTreePointer tree = getEntities()->getTree();
connect(tree.get(), &EntityTree::deletingEntity, this, &Application::deletingEntity, Qt::QueuedConnection);
connect(tree.get(), &EntityTree::addingEntity, this, &Application::addingEntity, Qt::QueuedConnection);
_entitySimulation->init(tree, _physicsEngine, &_entityEditSender);
tree->setSimulation(_entitySimulation);
@ -4879,14 +4877,16 @@ void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) {
auto entityId = _keyboardFocusedEntity.get();
if (entities->wantsKeyboardFocus(entityId)) {
entities->setProxyWindow(entityId, _window->windowHandle());
auto entity = getEntities()->getEntity(entityId);
if (_keyboardMouseDevice->isActive()) {
_keyboardMouseDevice->pluginFocusOutEvent();
}
_lastAcceptedKeyPress = usecTimestampNow();
setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(),
entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR);
auto entity = getEntities()->getEntity(entityId);
if (entity) {
setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(),
entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR);
}
}
}
}
@ -7675,12 +7675,4 @@ void Application::saveNextPhysicsStats(QString filename) {
_physicsEngine->saveNextPhysicsStats(filename);
}
void Application::addingEntity(const EntityItemID& entityID) {
// TODO: Andrew to implement this
}
void Application::deletingEntity(const EntityItemID& entityID) {
// TODO: Andrew to implement this
}
#include "Application.moc"

View file

@ -391,9 +391,6 @@ public slots:
const QString getPreferredCursor() const { return _preferredCursor.get(); }
void setPreferredCursor(const QString& cursor);
void addingEntity(const EntityItemID& entityID);
void deletingEntity(const EntityItemID& entityID);
private slots:
void onDesktopRootItemCreated(QQuickItem* qmlContext);
void onDesktopRootContextCreated(QQmlContext* qmlContext);

View file

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

View file

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

View file

@ -278,6 +278,13 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r
if (!entity->isParentPathComplete()) {
continue;
}
if (entity->getSpaceIndex() == -1) {
std::unique_lock<std::mutex> lock(_spaceLock);
workload::Space::Sphere sphere(entity->getWorldPosition(), entity->getBoundingRadius());
int32_t spaceIndex = _space.createProxy(sphere);
entity->setSpaceIndex(spaceIndex);
connect(entity.get(), &EntityItem::spaceUpdate, this, &EntityTreeRenderer::handleSpaceUpdate, Qt::QueuedConnection);
}
auto entityID = entity->getEntityItemID();
processedIds.insert(entityID);
@ -287,7 +294,6 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r
}
}
if (!processedIds.empty()) {
for (const auto& processedId : processedIds) {
_entitiesToAdd.erase(processedId);
@ -407,8 +413,7 @@ void EntityTreeRenderer::update(bool simulate) {
// here we update _currentFrame and _lastAnimated and sync with the server properties.
tree->update(simulate);
// Update the rendereable entities as needed
{
{ // Update the rendereable entities as needed
PROFILE_RANGE(simulation_physics, "Scene");
PerformanceTimer sceneTimer("scene");
auto scene = _viewState->getMain3DScene();
@ -421,6 +426,25 @@ void EntityTreeRenderer::update(bool simulate) {
scene->enqueueTransaction(transaction);
}
}
{ // update proxies in the workload::Space
std::unique_lock<std::mutex> lock(_spaceLock);
_space.updateProxies(_spaceUpdates);
_spaceUpdates.clear();
}
{ // flush final EntityTree references to removed entities
std::vector<EntityItemPointer> deletedEntities;
tree->swapRemovedEntities(deletedEntities);
{ // delete proxies from workload::Space
std::vector<int32_t> deadProxies;
std::unique_lock<std::mutex> lock(_spaceLock);
for (auto entity : deletedEntities) {
int32_t spaceIndex = entity->getSpaceIndex();
disconnect(entity.get(), &EntityItem::spaceUpdate, this, &EntityTreeRenderer::handleSpaceUpdate);
deadProxies.push_back(spaceIndex);
}
_space.deleteProxies(deadProxies);
}
}
if (simulate) {
// Handle enter/leave entity logic
@ -437,6 +461,11 @@ void EntityTreeRenderer::update(bool simulate) {
}
}
void EntityTreeRenderer::handleSpaceUpdate(std::pair<int32_t, glm::vec4> proxyUpdate) {
std::unique_lock<std::mutex> lock(_spaceLock);
_spaceUpdates.push_back(proxyUpdate);
}
bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QVector<EntityItemID>* entitiesContainingAvatar) {
bool didUpdate = false;
float radius = 0.01f; // for now, assume 0.01 meter radius, because we actually check the point inside later

View file

@ -24,6 +24,7 @@
#include <TextureCache.h>
#include <OctreeProcessor.h>
#include <render/Forward.h>
#include <workload/Space.h>
class AbstractScriptingServicesInterface;
class AbstractViewStateInterface;
@ -139,6 +140,10 @@ public slots:
EntityRendererPointer renderableForEntityId(const EntityItemID& id) const;
render::ItemID renderableIdForEntityId(const EntityItemID& id) const;
//void handleSpaceUpdate(workload::Space::ProxyUpdate proxyUpdate);
void handleSpaceUpdate(std::pair<int32_t, glm::vec4> proxyUpdate);
void testSlot();
protected:
virtual OctreePointer createTree() override {
EntityTreePointer newTree = EntityTreePointer(new EntityTree(true));
@ -261,6 +266,10 @@ private:
static std::function<bool()> _entitiesShouldFadeFunction;
static std::function<bool()> _renderDebugHullsOperator;
mutable std::mutex _spaceLock;
workload::Space _space;
std::vector<workload::Space::ProxyUpdate> _spaceUpdates;
};

View file

@ -2364,14 +2364,18 @@ void EntityItem::locationChanged(bool tellPhysics) {
tree->entityChanged(getThisPointer());
}
}
// TODO: Andrew to connect this to the Space instance in Application
SpatiallyNestable::locationChanged(tellPhysics); // tell all the children, also
std::pair<int32_t, glm::vec4> data(_spaceIndex, glm::vec4(getWorldPosition(), _boundingRadius));
emit spaceUpdate(data);
somethingChangedNotification();
}
void EntityItem::dimensionsChanged() {
requiresRecalcBoxes();
SpatiallyNestable::dimensionsChanged(); // Do what you have to do
_boundingRadius = 0.5f * glm::length(getScaledDimensions());
std::pair<int32_t, glm::vec4> data(_spaceIndex, glm::vec4(getWorldPosition(), _boundingRadius));
emit spaceUpdate(data);
somethingChangedNotification();
}

View file

@ -464,6 +464,7 @@ public:
virtual bool getMeshes(MeshProxyList& result) { return true; }
virtual void locationChanged(bool tellPhysics = true) override;
//void wtf(int32_t i) override;
virtual bool getScalesWithParent() const override;
@ -478,6 +479,7 @@ public:
void setCauterized(bool value) { _cauterized = value; }
bool getCauterized() const { return _cauterized; }
float getBoundingRadius() const { return _boundingRadius; }
void setSpaceIndex(int32_t index) { assert(_spaceIndex == -1); _spaceIndex = index; }
int32_t getSpaceIndex() const { return _spaceIndex; }
@ -490,6 +492,7 @@ public:
signals:
void requestRenderUpdate();
void spaceUpdate(std::pair<int32_t, glm::vec4> data);
protected:
QHash<ChangeHandlerId, ChangeHandlerCallback> _changeHandlers;
@ -641,6 +644,7 @@ protected:
quint64 _lastUpdatedAccelerationTimestamp { 0 };
quint64 _lastUpdatedQueryAACubeTimestamp { 0 };
float _boundingRadius { 0.0f };
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

View file

@ -260,7 +260,7 @@ void EntityTree::postAddEntity(EntityItemPointer entity) {
return;
}
}
// check to see if we need to simulate this entity..
if (_simulation) {
_simulation->addEntity(entity);
@ -271,10 +271,11 @@ void EntityTree::postAddEntity(EntityItemPointer entity) {
}
_isDirty = true;
emit addingEntity(entity->getEntityItemID());
// find and hook up any entities with this entity as a (previously) missing parent
fixupNeedsParentFixups();
emit addingEntity(entity->getEntityItemID());
}
bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode) {
@ -695,6 +696,11 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator)
if (_simulation) {
_simulation->prepareEntityForDelete(theEntity);
}
// We save a pointer to theEntity for external contexts that need it
// but this means: external contexts that remove entities from the tree
// must occasionally swapRemovedEntities() to flush these references.
_removedEntities.push_back(theEntity);
}
}

View file

@ -280,7 +280,7 @@ public:
void setMyAvatar(std::shared_ptr<AvatarData> myAvatar) { _myAvatar = myAvatar; }
void queueUpdateSpaceProxy(int32_t index, const glm::vec4& sphere);
void swapRemovedEntities(std::vector<EntityItemPointer>& entities) { entities.swap(_removedEntities); }
static void setAddMaterialToEntityOperator(std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> addMaterialToEntityOperator) { _addMaterialToEntityOperator = addMaterialToEntityOperator; }
static void setRemoveMaterialFromEntityOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> removeMaterialFromEntityOperator) { _removeMaterialFromEntityOperator = removeMaterialFromEntityOperator; }
@ -411,6 +411,8 @@ private:
static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromAvatarOperator;
static std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> _addMaterialToOverlayOperator;
static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromOverlayOperator;
std::vector<EntityItemPointer> _removedEntities;
};
#endif // hifi_EntityTree_h

View file

@ -40,7 +40,7 @@ void Space::deleteProxies(const std::vector<int32_t>& deadIndices) {
}
}
void Space::updateProxies(const std::vector<std::pair<int32_t, Sphere> >& changedProxies) {
void Space::updateProxies(const std::vector<ProxyUpdate>& changedProxies) {
for (uint32_t i = 0; i < changedProxies.size(); ++i) {
int32_t proxyId = changedProxies[i].first;
if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) {

View file

@ -29,6 +29,7 @@ public:
static const uint8_t REGION_INVALID = 4;
using Sphere = glm::vec4; // <x,y,z> = center, w = radius
using ProxyUpdate = std::pair<int32_t, Sphere>;
class Proxy {
public:
@ -61,7 +62,7 @@ public:
int32_t createProxy(const Sphere& sphere);
void deleteProxies(const std::vector<int32_t>& deadIndices);
void updateProxies(const std::vector<std::pair<int32_t, Sphere> >& changedProxies);
void updateProxies(const std::vector<ProxyUpdate>& changedProxies);
void setViews(const std::vector<View>& views);
uint32_t getNumObjects() const { return (uint32_t)(_proxies.size() - _freeIndices.size()); }