Update world transform job to use direct sync

Change-Id: Ie6cdb99332b5c99e583bdb7dfa5c4810ea5bba72
Reviewed-by: Mike Krus <mike.krus@kdab.com>
This commit is contained in:
Paul Lemire 2019-10-03 11:04:27 +02:00
parent f29a8c502f
commit 48ff8579fe
5 changed files with 45 additions and 40 deletions

View File

@ -131,15 +131,6 @@ void Transform::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
BackendNode::syncFromFrontEnd(frontEnd, firstTime);
}
void Transform::notifyWorldTransformChanged(const Matrix4x4 &worldMatrix)
{
auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
change->setPropertyName("worldMatrix");
change->setValue(convertToQMatrix4x4(worldMatrix));
notifyObservers(change);
}
void Transform::updateMatrix()
{
QMatrix4x4 m;

View File

@ -78,7 +78,6 @@ public:
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) final;
void notifyWorldTransformChanged(const Matrix4x4 &worldMatrix);
private:
void updateMatrix();

View File

@ -39,6 +39,9 @@
#include "updateworldtransformjob_p.h"
#include <Qt3DCore/qtransform.h>
#include <Qt3DCore/private/qtransform_p.h>
#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/entity_p.h>
#include <Qt3DRender/private/transform_p.h>
@ -56,10 +59,17 @@ namespace Render {
namespace {
void updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Matrix4x4 &parentTransform)
struct TransformUpdate
{
Qt3DCore::QNodeId peerId;
QMatrix4x4 worldTransformMatrix;
};
QVector<TransformUpdate> updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Matrix4x4 &parentTransform)
{
Matrix4x4 worldTransform(parentTransform);
Transform *nodeTransform = node->renderComponent<Transform>();
QVector<TransformUpdate> updatedTransforms;
const bool hasTransformComponent = nodeTransform != nullptr && nodeTransform->isEnabled();
if (hasTransformComponent)
@ -68,21 +78,33 @@ void updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Ma
if (*(node->worldTransform()) != worldTransform) {
*(node->worldTransform()) = worldTransform;
if (hasTransformComponent)
nodeTransform->notifyWorldTransformChanged(worldTransform);
updatedTransforms.push_back({nodeTransform->peerId(), convertToQMatrix4x4(worldTransform)});
}
const auto childrenHandles = node->childrenHandles();
for (const HEntity &handle : childrenHandles) {
Entity *child = manager->renderNodesManager()->data(handle);
if (child)
updateWorldTransformAndBounds(manager, child, worldTransform);
updatedTransforms += updateWorldTransformAndBounds(manager, child, worldTransform);
}
return updatedTransforms;
}
}
class Q_3DRENDERSHARED_PRIVATE_EXPORT UpdateWorldTransformJobPrivate : public Qt3DCore::QAspectJobPrivate
{
public:
UpdateWorldTransformJobPrivate() {}
~UpdateWorldTransformJobPrivate() override {}
void postFrame(Qt3DCore::QAspectManager *manager) override;
QVector<TransformUpdate> m_updatedTransforms;
};
UpdateWorldTransformJob::UpdateWorldTransformJob()
: Qt3DCore::QAspectJob()
: Qt3DCore::QAspectJob(*new UpdateWorldTransformJobPrivate())
, m_node(nullptr)
, m_manager(nullptr)
{
@ -108,17 +130,32 @@ void UpdateWorldTransformJob::run()
// TODO: Parallelise this on each level using a parallel_for
// implementation.
Q_D(UpdateWorldTransformJob);
qCDebug(Jobs) << "Entering" << Q_FUNC_INFO << QThread::currentThread();
Matrix4x4 parentTransform;
Entity *parent = m_node->parent();
if (parent != nullptr)
parentTransform = *(parent->worldTransform());
updateWorldTransformAndBounds(m_manager, m_node, parentTransform);
d->m_updatedTransforms = updateWorldTransformAndBounds(m_manager, m_node, parentTransform);
qCDebug(Jobs) << "Exiting" << Q_FUNC_INFO << QThread::currentThread();
}
void UpdateWorldTransformJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
{
const QVector<TransformUpdate> updatedTransforms = std::move(m_updatedTransforms);
for (const TransformUpdate &t : updatedTransforms) {
Qt3DCore::QTransform *node =
qobject_cast<Qt3DCore::QTransform *>(manager->lookupNode(t.peerId));
if (!node)
continue;
Qt3DCore::QTransformPrivate *dNode =
static_cast<Qt3DCore::QTransformPrivate *>(Qt3DCore::QNodePrivate::get(node));
dNode->setWorldMatrix(t.worldTransformMatrix);
}
}
} // namespace Render
} // namespace Qt3DRender

View File

@ -63,6 +63,7 @@ namespace Render {
class Entity;
class NodeManagers;
class UpdateWorldTransformJobPrivate;
class Q_3DRENDERSHARED_PRIVATE_EXPORT UpdateWorldTransformJob : public Qt3DCore::QAspectJob
{
@ -77,6 +78,7 @@ public:
private:
Entity *m_node;
NodeManagers *m_manager;
Q_DECLARE_PRIVATE(UpdateWorldTransformJob)
};
typedef QSharedPointer<UpdateWorldTransformJob> UpdateWorldTransformJobPtr;

View File

@ -31,6 +31,7 @@
#include <Qt3DCore/qtransform.h>
#include <Qt3DCore/private/qtransform_p.h>
#include <Qt3DRender/private/transform_p.h>
#include <Qt3DRender/private/updateworldtransformjob_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <private/qbackendnode_p.h>
#include "qbackendnodetester.h"
@ -179,31 +180,6 @@ private Q_SLOTS:
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
}
}
void checkWorldTransformUpdate()
{
// GIVEN
TestArbiter arbiter;
Qt3DRender::Render::Transform backend;
Qt3DCore::QBackendNodePrivate::get(&backend)->setArbiter(&arbiter);
// WHEN
const QMatrix4x4 expectedNewWorldMatrix(1.0f, 2.0f, 3.0f, 4.0f,
5.0f, 6.0f, 7.0f, 8.0f,
9.0f, 10.0f, 11.0f, 12.0f,
13.0f, 14.0f, 15.0f, 16.0f);
Matrix4x4 newWorldMatrix(expectedNewWorldMatrix);
backend.notifyWorldTransformChanged(newWorldMatrix);
// THEN
Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
QCOMPARE(arbiter.events.count(), 1);
QCOMPARE(change->propertyName(), "worldMatrix");
QCOMPARE(change->value().value<QMatrix4x4>(), expectedNewWorldMatrix);
arbiter.events.clear();
}
};
QTEST_MAIN(tst_Transform)