Commit f51b00bc authored by Richard Gustavsen's avatar Richard Gustavsen

QQuick3DNode: ensure we register changes to global transform

Anyone can call calculateGlobalVariables() at any time. So by the
time the global transform pass calls out to the node, the
calulation might already have been done. So for those cases, ensure
that we always store if the global transform has changed whenever
we calculate global variables.
parent e266578e
Pipeline #5033 passed with stage
in 4 minutes and 43 seconds
......@@ -321,22 +321,46 @@ QMatrix4x4 QQuick3DNode::globalTransformLeftHanded() const
*/
QMatrix4x4 QQuick3DNode::globalTransformRightHanded() const
{
// TODO: don't call this if not dirty
const_cast<QQuick3DNode *>(this)->calculateGlobalVariables();
return m_globalTransformRightHanded;
}
void QQuick3DNode::calculateGlobalVariables()
{
// TODO: return early if nothing we're about to calculate is dirty
const QMatrix4x4 prevGlobalTransform = m_globalTransformRightHanded;
QMatrix4x4 localTransformRightHanded = calculateLocalTransformRightHanded();
QQuick3DNode *parent = parentNode();
if (!parent) {
if (QQuick3DNode *parent = parentNode()) {
parent->calculateGlobalVariables();
m_globalTransformRightHanded = parent->m_globalTransformRightHanded * localTransformRightHanded;
} else {
m_globalTransformRightHanded = localTransformRightHanded;
return;
}
parent->calculateGlobalVariables();
m_globalTransformRightHanded = parent->m_globalTransformRightHanded * localTransformRightHanded;
if (m_globalTransformConnectionCount != 0)
bookkeepChangesToGlobalTransform(prevGlobalTransform, m_globalTransformRightHanded);
}
void QQuick3DNode::bookkeepChangesToGlobalTransform(const QMatrix4x4 &oldMatrix, const QMatrix4x4 &newMatrix)
{
if (!m_globalPositionPendingEmit) {
const QVector3D oldGlobalPosition = mat44::getPosition(oldMatrix);
const QVector3D newGlobalPosition = mat44::getPosition(newMatrix);
m_globalPositionPendingEmit = oldGlobalPosition != newGlobalPosition;
}
if (!m_globalRotationPendingEmit) {
const QVector3D oldGlobalRotation = mat44::getRotation(oldMatrix, m_rotationorder);
const QVector3D newGlobalRotation = mat44::getRotation(newMatrix, m_rotationorder);
m_globalRotationPendingEmit = oldGlobalRotation != newGlobalRotation;
}
if (!m_globalScalePendingEmit) {
const QVector3D oldGlobalScale = mat44::getScale(oldMatrix);
const QVector3D newGlobalScale = mat44::getScale(newMatrix);
m_globalScalePendingEmit = oldGlobalScale != newGlobalScale;
}
}
QMatrix4x4 QQuick3DNode::calculateLocalTransformRightHanded()
......@@ -371,27 +395,27 @@ QMatrix4x4 QQuick3DNode::calculateLocalTransformRightHanded()
return localTransform;
}
void QQuick3DNode::calculateAndNotifyGlobalTransformChanges()
void QQuick3DNode::emitChangesToGlobalTransform()
{
const QMatrix4x4 oldGlobalTransform = m_globalTransformRightHanded;
const QMatrix4x4 newGlobalTransform = globalTransformRightHanded();
if (oldGlobalTransform == newGlobalTransform)
if (!m_globalPositionPendingEmit && !m_globalRotationPendingEmit && !m_globalScalePendingEmit)
return;
const QVector3D oldGlobalPosition = mat44::getPosition(oldGlobalTransform);
const QVector3D newGlobalPosition = mat44::getPosition(newGlobalTransform);
const QVector3D oldGlobalRotation = mat44::getRotation(oldGlobalTransform, m_rotationorder);
const QVector3D newGlobalRotation = mat44::getRotation(newGlobalTransform, m_rotationorder);
const QVector3D oldGlobalScale = mat44::getScale(oldGlobalTransform);
const QVector3D newGlobalScale = mat44::getScale(newGlobalTransform);
emit globalTransformChanged();
if (oldGlobalPosition != newGlobalPosition)
if (m_globalPositionPendingEmit) {
m_globalPositionPendingEmit = false;
emit globalPositionChanged();
if (oldGlobalRotation != newGlobalRotation)
}
if (m_globalRotationPendingEmit) {
m_globalRotationPendingEmit = false;
emit globalRotationChanged();
if (oldGlobalScale != newGlobalScale)
}
if (m_globalScalePendingEmit) {
m_globalScalePendingEmit = false;
emit globalScaleChanged();
}
}
bool QQuick3DNode::isGlobalTransformRelatedSignal(const QMetaMethod &signal)
......
......@@ -174,12 +174,17 @@ private:
Orientation m_orientation = LeftHanded;
bool m_visible = true;
QMatrix4x4 m_globalTransformRightHanded;
int m_globalTransformConnectionCount = 0;
bool m_globalPositionPendingEmit = false;
bool m_globalRotationPendingEmit = false;
bool m_globalScalePendingEmit = false;
void calculateAndNotifyGlobalTransformChanges();
QMatrix4x4 calculateLocalTransformRightHanded();
void calculateGlobalVariables();
inline void bookkeepChangesToGlobalTransform(const QMatrix4x4 &oldMatrix, const QMatrix4x4 &newMatrix);
void emitChangesToGlobalTransform();
bool isGlobalTransformRelatedSignal(const QMetaMethod &signal);
void updateGlobalTransformRegistration();
......
......@@ -192,8 +192,10 @@ void QQuick3DSceneManager::updateGlobalTransformNodes()
// to the root, we instead optimize this by checking it once in a separate pass. This needs
// to be done whenever another node in the scene changes transform, since we don't know upfront
// if that change might affect any of the globalTransformNodes as well.
for (const auto globalTransformNode : globalTransformNodes)
globalTransformNode->calculateAndNotifyGlobalTransformChanges();
for (const auto globalTransformNode : globalTransformNodes) {
globalTransformNode->calculateGlobalVariables();
globalTransformNode->emitChangesToGlobalTransform();
}
}
QQuick3DObject *QQuick3DSceneManager::lookUpNode(QSSGRenderGraphObject *node) const
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment