From 961f7e783670be0627ddb21c1379ebfec0c3c944 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 8 Mar 2019 16:15:29 +0200 Subject: Improve scene translation push efficiency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to remove all scene content and recreate the layers every time anything changes in the scene. Change-Id: I16d9401f1977d5bcc4ac27d864800eb1db1d972e Reviewed-by: Mahmoud Badri Reviewed-by: Antti Määttä Reviewed-by: Tomi Korpipää --- src/Authoring/Studio/Render/Q3DSTranslation.cpp | 29 ++++++----- src/Authoring/Studio/Render/Q3DSTranslation.h | 2 +- src/Authoring/Studio/Render/Q3DSTranslators.cpp | 67 ++++++++++++++++++++++--- 3 files changed, 78 insertions(+), 20 deletions(-) diff --git a/src/Authoring/Studio/Render/Q3DSTranslation.cpp b/src/Authoring/Studio/Render/Q3DSTranslation.cpp index 311fac57..3e102481 100644 --- a/src/Authoring/Studio/Render/Q3DSTranslation.cpp +++ b/src/Authoring/Studio/Render/Q3DSTranslation.cpp @@ -608,8 +608,14 @@ void Q3DSTranslation::markPropertyDirty(qt3dsdm::Qt3DSDMInstanceHandle instance, void Q3DSTranslation::releaseTranslation(qt3dsdm::Qt3DSDMInstanceHandle instance) { THandleTranslatorPairList &theTranslators = getTranslatorsForInstance(instance); - for (int idx = 0, end = theTranslators.size(); idx < end; ++idx) - m_releaseSet.insert(*theTranslators[idx].second); + for (int idx = 0, end = theTranslators.size(); idx < end; ++idx) { + // We want to release translators immediately, otherwise it is difficult to ensure + // correct order of operations when multiple commands affecting same objects occur + // within the same frame. + auto translator = theTranslators[idx].second; + translator->releaseGraphObjectsRecursive(*this); + releaseTranslator(translator); + } m_studioRenderer.RequestRender(); } @@ -1025,24 +1031,18 @@ void Q3DSTranslation::releaseTranslator(Q3DSGraphObjectTranslator *translator) m_instanceIdHash.remove(instance); m_translatorMap.remove(instance); m_presentation->unlinkObject(graphObject); + m_dirtySet.remove(*translator); delete translator; delete graphObject; } void Q3DSTranslation::clearDirtySet() { - for (unsigned int idx = 0; idx < m_releaseSet.size(); ++idx) { - Q3DSGraphObjectTranslator *translator = m_releaseSet[idx]; - translator->releaseGraphObjectsRecursive(*this); - releaseTranslator(translator); - } for (unsigned int idx = 0; idx < m_dirtySet.size(); ++idx) { - if (m_reader.IsInstance(m_dirtySet[idx]->instanceHandle()) - && m_dirtySet[idx]->dirty()) { - m_dirtySet[idx]->pushTranslation(*this); - } + Q3DSGraphObjectTranslator *translator = m_dirtySet[idx]; + if (m_reader.IsInstance(translator->instanceHandle()) && translator->dirty()) + translator->pushTranslation(*this); } - m_releaseSet.clear(); m_dirtySet.clear(); updateForegroundLayerProperties(); @@ -2360,4 +2360,9 @@ void Q3DSTranslation::editCameraZoomToFit() m_editCameraInfo.m_position = center - m_editCameraInfo.front() * 600.f; } +bool Q3DSTranslation::isHelperLayer(const Q3DSGraphObject *obj) const +{ + return m_backgroundLayer == obj || m_foregroundLayer == obj || m_foregroundPickingLayer == obj; +} + } diff --git a/src/Authoring/Studio/Render/Q3DSTranslation.h b/src/Authoring/Studio/Render/Q3DSTranslation.h index a15c7036..ad4dbe59 100644 --- a/src/Authoring/Studio/Render/Q3DSTranslation.h +++ b/src/Authoring/Studio/Render/Q3DSTranslation.h @@ -182,7 +182,6 @@ private: // All translator related containers must come after the allocator TInstanceToTranslatorMap m_translatorMap; TTranslatorDirtySet m_dirtySet; - TTranslatorDirtySet m_releaseSet; Q3DSPresentationData m_presentation_data; Q3DSScene *m_scene; Q3DStudio::CGraphIterator m_graphIterator; @@ -320,6 +319,7 @@ public: void rotateAlongWidget(const QPoint &inOriginalCoords, const QPoint &inMouseCoords, CUpdateableDocumentEditor &inEditor); void editCameraZoomToFit(); + bool isHelperLayer(const Q3DSGraphObject *obj) const; }; } diff --git a/src/Authoring/Studio/Render/Q3DSTranslators.cpp b/src/Authoring/Studio/Render/Q3DSTranslators.cpp index 752caffb..2db4a74a 100644 --- a/src/Authoring/Studio/Render/Q3DSTranslators.cpp +++ b/src/Authoring/Studio/Render/Q3DSTranslators.cpp @@ -815,16 +815,69 @@ void Q3DSSceneTranslator::pushTranslation(Q3DSTranslation &inContext) Q3DSTranslatorDataModelParser theParser(inContext, instanceHandle()); Q3DSPropertyChangeList list; ITERATE_Q3DS_SCENE_PROPERTIES - theItem.removeAllChildNodes(); - int childCount = inContext.assetGraph().GetChildCount(instanceHandle()); + + // Check if there are any changes to layer children + // First collect a set of existing child objects of the scene, excluding helper layers + int oldChildCount = theItem.childCount(); + QVector oldChildren; + oldChildren.reserve(oldChildCount); + for (int i = 0; i < oldChildCount; ++i) { + Q3DSGraphObject *obj = theItem.childAtIndex(i); + if (!inContext.isHelperLayer(obj)) + oldChildren << obj; + } + oldChildCount = oldChildren.size(); + + // Collect current children in asset graph + int newChildCount = inContext.assetGraph().GetChildCount(instanceHandle()); QVector translators; - for (long idx = 0; idx < childCount; ++idx) { - qt3dsdm::Qt3DSDMInstanceHandle child = - inContext.assetGraph().GetChild(instanceHandle(), idx); + translators.reserve(newChildCount); + QVector newChildren; + newChildren.reserve(newChildCount); + for (long i = 0; i < newChildCount; ++i) { + qt3dsdm::Qt3DSDMInstanceHandle child + = inContext.assetGraph().GetChild(instanceHandle(), i); Q3DSGraphObjectTranslator *translator = inContext.getOrCreateTranslator(child); - theItem.appendChildNode(&translator->graphObject()); - translators << translator; + if (translator) { // Script items do not get translators + translators << translator; + newChildren << &translator->graphObject(); + } + } + + // Remove nodes that have been reordered + newChildCount = newChildren.size(); + for (int newIdx = 0, oldIdx = 0; newIdx < newChildCount && oldIdx < oldChildCount;) { + auto newChild = newChildren[newIdx]; + auto oldChild = oldChildren[oldIdx]; + if (!oldChildren.contains(newChild)) { + ++newIdx; + } else { + if (oldChild != newChild) { + theItem.removeChildNode(oldChild); + ++oldIdx; + } else { + ++oldIdx; + ++newIdx; + } + } } + + // Now insert new and moved nodes back to correct positions + Q3DSGraphObject *nextChild = theItem.firstChild(); + while (nextChild && inContext.isHelperLayer(nextChild)) + nextChild = nextChild->nextSibling(); + for (int newIdx = 0; newIdx < newChildCount; ++newIdx) { + auto child = newChildren[newIdx]; + if (nextChild != child) { + if (!nextChild) + theItem.appendChildNode(child); + else + theItem.insertChildNodeBefore(child, nextChild); + } else if (nextChild) { + nextChild = nextChild->nextSibling(); + } + } + theItem.resolveReferences(*inContext.presentation()); for (auto t : qAsConst(translators)) t->pushTranslationIfDirty(inContext); -- cgit v1.2.3