Merge pull request #11421 from jherico/fix/transform_log_spam

Don't add items to the scene graph until they have a valid parent chain
This commit is contained in:
Andrew Meadows 2017-09-21 08:42:56 -07:00 committed by GitHub
commit b803344f0c
7 changed files with 107 additions and 43 deletions

View file

@ -159,6 +159,78 @@ void EntityTreeRenderer::shutdown() {
clear(); // always clear() on shutdown clear(); // always clear() on shutdown
} }
void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, render::Transaction& transaction) {
// Clear any expired entities
// FIXME should be able to use std::remove_if, but it fails due to some
// weird compilation error related to EntityItemID assignment operators
for (auto itr = _entitiesToAdd.begin(); _entitiesToAdd.end() != itr; ) {
if (itr->second.expired()) {
_entitiesToAdd.erase(itr++);
} else {
++itr;
}
}
if (!_entitiesToAdd.empty()) {
std::unordered_set<EntityItemID> processedIds;
for (const auto& entry : _entitiesToAdd) {
auto entity = entry.second.lock();
if (!entity) {
continue;
}
// Path to the parent transforms is not valid,
// don't add to the scene graph yet
if (!entity->isParentPathComplete()) {
continue;
}
auto entityID = entity->getEntityItemID();
processedIds.insert(entityID);
auto renderable = EntityRenderer::addToScene(*this, entity, scene, transaction);
if (renderable) {
_entitiesInScene.insert({ entityID, renderable });
}
}
if (!processedIds.empty()) {
for (const auto& processedId : processedIds) {
_entitiesToAdd.erase(processedId);
}
}
}
}
void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, render::Transaction& transaction) {
std::unordered_set<EntityItemID> changedEntities;
_changedEntitiesGuard.withWriteLock([&] {
#if 0
// FIXME Weird build failure in latest VC update that fails to compile when using std::swap
changedEntities.swap(_changedEntities);
#else
changedEntities.insert(_changedEntities.begin(), _changedEntities.end());
_changedEntities.clear();
#endif
});
for (const auto& entityId : changedEntities) {
auto renderable = renderableForEntityId(entityId);
if (!renderable) {
continue;
}
_renderablesToUpdate.insert({ entityId, renderable });
}
if (!_renderablesToUpdate.empty()) {
for (const auto& entry : _renderablesToUpdate) {
const auto& renderable = entry.second;
renderable->updateInScene(scene, transaction);
}
_renderablesToUpdate.clear();
}
}
void EntityTreeRenderer::update(bool simulate) { void EntityTreeRenderer::update(bool simulate) {
PerformanceTimer perfTimer("ETRupdate"); PerformanceTimer perfTimer("ETRupdate");
if (_tree && !_shuttingDown) { if (_tree && !_shuttingDown) {
@ -178,30 +250,11 @@ void EntityTreeRenderer::update(bool simulate) {
} }
} }
std::unordered_set<EntityItemID> changedEntities;
// FIXME Weird build failure in latest VC update that fails to compile when using std::swap
_changedEntitiesGuard.withWriteLock([&] {
changedEntities.insert(_changedEntities.begin(), _changedEntities.end());
_changedEntities.clear();
});
for (const auto& entityId : changedEntities) {
auto renderable = renderableForEntityId(entityId);
if (!renderable) {
continue;
}
_renderablesToUpdate.insert({ entityId, renderable });
}
auto scene = _viewState->getMain3DScene(); auto scene = _viewState->getMain3DScene();
if (scene && !_renderablesToUpdate.empty()) { if (scene) {
render::Transaction transaction; render::Transaction transaction;
for (const auto& entry : _renderablesToUpdate) { addPendingEntities(scene, transaction);
const auto& renderable = entry.second; updateChangedEntities(scene, transaction);
renderable->updateInScene(scene, transaction);
}
_renderablesToUpdate.clear();
scene->enqueueTransaction(transaction); scene->enqueueTransaction(transaction);
} }
} }
@ -689,8 +742,12 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
} }
void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) {
// If it's in the pending queue, remove it
_entitiesToAdd.erase(entityID);
auto itr = _entitiesInScene.find(entityID); auto itr = _entitiesInScene.find(entityID);
if (_entitiesInScene.end() == itr) { if (_entitiesInScene.end() == itr) {
// Not in the scene, and no longer potentially in the pending queue, we're done
return; return;
} }
@ -725,25 +782,10 @@ void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) {
checkAndCallPreload(entityID); checkAndCallPreload(entityID);
auto entity = std::static_pointer_cast<EntityTree>(_tree)->findEntityByID(entityID); auto entity = std::static_pointer_cast<EntityTree>(_tree)->findEntityByID(entityID);
if (entity) { if (entity) {
addEntityToScene(entity); _entitiesToAdd.insert({ entity->getEntityItemID(), entity });
} }
} }
void EntityTreeRenderer::addEntityToScene(const EntityItemPointer& entity) {
// here's where we add the entity payload to the scene
auto scene = _viewState->getMain3DScene();
if (!scene) {
qCWarning(entitiesrenderer) << "EntityTreeRenderer::addEntityToScene(), Unexpected null scene, possibly during application shutdown";
return;
}
auto renderable = EntityRenderer::addToScene(*this, entity, scene);
if (renderable) {
_entitiesInScene[entity->getEntityItemID()] = renderable;
}
}
void EntityTreeRenderer::entityScriptChanging(const EntityItemID& entityID, bool reload) { void EntityTreeRenderer::entityScriptChanging(const EntityItemID& entityID, bool reload) {
checkAndCallPreload(entityID, reload, true); checkAndCallPreload(entityID, reload, true);
} }

View file

@ -36,6 +36,7 @@ namespace render { namespace entities {
class EntityRenderer; class EntityRenderer;
using EntityRendererPointer = std::shared_ptr<EntityRenderer>; using EntityRendererPointer = std::shared_ptr<EntityRenderer>;
using EntityRendererWeakPointer = std::weak_ptr<EntityRenderer>; using EntityRendererWeakPointer = std::weak_ptr<EntityRenderer>;
} } } }
// Allow the use of std::unordered_map with QUuid keys // Allow the use of std::unordered_map with QUuid keys
@ -157,12 +158,13 @@ protected:
} }
private: private:
void addPendingEntities(const render::ScenePointer& scene, render::Transaction& transaction);
void updateChangedEntities(const render::ScenePointer& scene, render::Transaction& transaction);
EntityRendererPointer renderableForEntity(const EntityItemPointer& entity) const { return renderableForEntityId(entity->getID()); } EntityRendererPointer renderableForEntity(const EntityItemPointer& entity) const { return renderableForEntityId(entity->getID()); }
render::ItemID renderableIdForEntity(const EntityItemPointer& entity) const { return renderableIdForEntityId(entity->getID()); } render::ItemID renderableIdForEntity(const EntityItemPointer& entity) const { return renderableIdForEntityId(entity->getID()); }
void resetEntitiesScriptEngine(); void resetEntitiesScriptEngine();
void addEntityToScene(const EntityItemPointer& entity);
bool findBestZoneAndMaybeContainingEntities(QVector<EntityItemID>* entitiesContainingAvatar = nullptr); bool findBestZoneAndMaybeContainingEntities(QVector<EntityItemID>* entitiesContainingAvatar = nullptr);
bool applyLayeredZones(); bool applyLayeredZones();
@ -260,6 +262,7 @@ private:
std::unordered_map<EntityItemID, EntityRendererPointer> _renderablesToUpdate; std::unordered_map<EntityItemID, EntityRendererPointer> _renderablesToUpdate;
std::unordered_map<EntityItemID, EntityRendererPointer> _entitiesInScene; std::unordered_map<EntityItemID, EntityRendererPointer> _entitiesInScene;
std::unordered_map<EntityItemID, EntityItemWeakPointer> _entitiesToAdd;
// For Scene.shouldRenderEntities // For Scene.shouldRenderEntities
QList<EntityItemID> _entityIDsLastInScene; QList<EntityItemID> _entityIDsLastInScene;

View file

@ -187,7 +187,7 @@ void EntityRenderer::render(RenderArgs* args) {
// Methods called by the EntityTreeRenderer // Methods called by the EntityTreeRenderer
// //
EntityRenderer::Pointer EntityRenderer::addToScene(EntityTreeRenderer& renderer, const EntityItemPointer& entity, const ScenePointer& scene) { EntityRenderer::Pointer EntityRenderer::addToScene(EntityTreeRenderer& renderer, const EntityItemPointer& entity, const ScenePointer& scene, Transaction& transaction) {
EntityRenderer::Pointer result; EntityRenderer::Pointer result;
if (!entity) { if (!entity) {
return result; return result;
@ -245,9 +245,7 @@ EntityRenderer::Pointer EntityRenderer::addToScene(EntityTreeRenderer& renderer,
} }
if (result) { if (result) {
Transaction transaction;
result->addToScene(scene, transaction); result->addToScene(scene, transaction);
scene->enqueueTransaction(transaction);
} }
return result; return result;

View file

@ -30,7 +30,7 @@ class EntityRenderer : public QObject, public std::enable_shared_from_this<Entit
public: public:
static void initEntityRenderers(); static void initEntityRenderers();
static Pointer addToScene(EntityTreeRenderer& renderer, const EntityItemPointer& entity, const ScenePointer& scene); static Pointer addToScene(EntityTreeRenderer& renderer, const EntityItemPointer& entity, const ScenePointer& scene, Transaction& transaction);
// Allow classes to override this to interact with the user // Allow classes to override this to interact with the user
virtual bool wantsHandControllerPointerEvents() const { return false; } virtual bool wantsHandControllerPointerEvents() const { return false; }

View file

@ -28,6 +28,7 @@ namespace render {
class Scene; class Scene;
using ScenePointer = std::shared_ptr<Scene>; using ScenePointer = std::shared_ptr<Scene>;
class ShapePipeline; class ShapePipeline;
class Transaction;
} }
using RenderArgs = render::Args; using RenderArgs = render::Args;

View file

@ -1182,3 +1182,19 @@ void SpatiallyNestable::dump(const QString& prefix) const {
parent->dump(prefix + " "); parent->dump(prefix + " ");
} }
} }
bool SpatiallyNestable::isParentPathComplete() const {
static const QUuid IDENTITY;
QUuid parentID = getParentID();
if (parentID.isNull() || parentID == IDENTITY) {
return true;
}
bool success = false;
SpatiallyNestablePointer parent = getParentPointer(success);
if (!success || !parent) {
return false;
}
return parent->isParentPathComplete();
}

View file

@ -66,6 +66,10 @@ public:
static QString nestableTypeToString(NestableType nestableType); static QString nestableTypeToString(NestableType nestableType);
virtual bool isParentPathComplete() const;
// world frame // world frame
virtual const Transform getTransform(bool& success, int depth = 0) const; virtual const Transform getTransform(bool& success, int depth = 0) const;
virtual const Transform getTransform() const; virtual const Transform getTransform() const;