/**************************************************************************** ** ** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of Qt 3D Studio. ** ** $QT_BEGIN_LICENSE:GPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 or (at your option) any later version ** approved by the KDE Free Qt Foundation. The licenses are as published by ** the Free Software Foundation and appearing in the file LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "dragontransformjobs_p.h" #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE using namespace Qt3DCore; namespace Qt3DRender { namespace Dragon { ValueContainer calculateWorldTransforms(ValueContainer worldTransforms, const ValueContainer &entities, const ValueContainer &transforms, QNodeId rootEntityId) { worldTransforms.reset(); if (!entities.anythingDirty() && !transforms.anythingDirty()) return worldTransforms; struct Data { Data() { } Data(QNodeId entityId_, bool dirty_) : entityId(entityId_), dirty(dirty_) { } QNodeId entityId; bool dirty = false; }; const auto &dirtyTransforms = transforms.dirtyOrNew(); const auto &dirtyEntities = entities.dirtyOrNew(); // If entities are dirty, a transform component may have changed and we set the entire tree to // be recalculated. Note that this could be optimized. bool rootDirty = entities.anythingDirty(); const auto &rootEntity = entities[rootEntityId]; if (rootEntity->m_transformComponent.isNull()) { worldTransforms[rootEntityId] = Matrix4x4{}; } else { const auto &transform = transforms[rootEntity->m_transformComponent]; if (transforms.dirty().contains(rootEntity->m_transformComponent)) rootDirty = true; worldTransforms[rootEntityId] = transform->m_transformMatrix; } QStack stack; stack.reserve(10); stack.push({ rootEntityId, rootDirty }); while (!stack.isEmpty()) { auto currentItem = stack.pop(); QNodeId currentId = currentItem.entityId; bool currentDirty = currentItem.dirty; if (currentDirty) worldTransforms.markDirty(currentId); const auto ¤tWorldTransform = *worldTransforms[currentId]; const auto &children = entities[currentId]->treeChildren(); // Iterate the children in reverse order (because the stack is last-in-first-out) // TODO use std::reverse_iterator once we have C++17 for (auto it = children.rbegin(); it != children.rend(); ++it) { const auto &childId = *it; const auto &childEntity = entities[childId]; bool childDirty = currentDirty || dirtyEntities.contains(childId); if (!childEntity->m_transformComponent.isNull()) { const auto &transform = transforms[childEntity->m_transformComponent]; childDirty |= dirtyTransforms.contains(childEntity->m_transformComponent); if (childDirty) worldTransforms[childId] = currentWorldTransform * transform->m_transformMatrix; } else { if (childDirty) worldTransforms[childId] = currentWorldTransform; } stack.push({ childId, childDirty }); } } return worldTransforms; }; bool printTransforms(const ValueContainer &transforms) { Q_UNUSED(transforms); // for (const auto &transform : transforms) { // qDebug() << "Value:" << transform.get(); // } return true; // dummy, because we currently cannot return void } } // namespace Dragon } // namespace Qt3DRender QT_END_NAMESPACE