diff options
author | Sarah Smith <sarah.j.smith@nokia.com> | 2011-11-27 14:16:04 -0800 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-12-01 05:24:02 +0100 |
commit | 6502c4da8a725d6bf908266826b00fa2862ca1ee (patch) | |
tree | e9ecf799edf9e45843100a4a5791b9ec2dca5769 | |
parent | d6a188c6136c33b5079878529d425c0d39d17fe1 (diff) |
Improve qDumpScene.
The output of this useful debugging tool was a bit erratic, with
spurious newlines, and hard to read formatting. Fix, that and also
while on the job improve formatting, and fix the fact that it became
undefined with QT_NO_DEBUG_STREAM which could result in programs
breaking when defines were changed. Now if QT_NO_DEBUG_STREAM is
defined the function is still there, but just exits without doing
anything. Also add a non-detailed mode for quick summaries, and for
complex scenes where too much detail would be produced.
Add a debugging flag to the viewport. Get a dump of the scene when you
set a showSceneGraph flag in your qml. This could be improved as it
does not handle cases where the Item3D's are in components. Its a good
start.
Change-Id: I8a5ef3e8739dbe72617aad33377c691838a06fa2
Reviewed-by: Patrick Burke <patrick.burke@nokia.com>
-rw-r--r-- | src/imports/threed/viewport.cpp | 34 | ||||
-rw-r--r-- | src/imports/threed/viewport.h | 7 | ||||
-rw-r--r-- | src/quick3d/qdeclarativeitem3d.cpp | 39 | ||||
-rw-r--r-- | src/quick3d/qdeclarativeitem3d.h | 2 | ||||
-rw-r--r-- | src/threed/scene/qglscenenode.cpp | 138 | ||||
-rw-r--r-- | src/threed/scene/qglscenenode.h | 4 |
6 files changed, 172 insertions, 52 deletions
diff --git a/src/imports/threed/viewport.cpp b/src/imports/threed/viewport.cpp index 0309f6fb..5f4169e3 100644 --- a/src/imports/threed/viewport.cpp +++ b/src/imports/threed/viewport.cpp @@ -99,6 +99,8 @@ public: bool picking; bool showPicking; + bool showSceneGraph; + int dumpCount; bool navigation; bool fovzoom; bool blending; @@ -129,6 +131,8 @@ public: ViewportPrivate::ViewportPrivate() : picking(false) , showPicking(false) + , showSceneGraph(false) + , dumpCount(10) // maybe this needs to be higher? , navigation(true) , fovzoom(false) , blending(false) @@ -256,6 +260,30 @@ void Viewport::setShowPicking(bool value) } /*! + \qmlproperty bool Viewport::showSceneGraph + + This property controls whether or not the 3D scenegraph structure is dumped + to the console when the viewport is first rendered. Studying the output can be very + useful for optimising the scene, and for detecting issues with rendering, such + as misplaced textures, materials, geometry and so on. + + By default the value is set to false. +*/ +bool Viewport::showSceneGraph() const +{ + return d->showSceneGraph; +} + +void Viewport::setShowSceneGraph(bool show) +{ + if (show != d->showSceneGraph) + { + d->showSceneGraph = show; + emit showSceneGraphChanged(); + } +} + +/*! \qmlproperty bool Viewport::navigation This property is used to set or unset camera navigation in for the viewport. @@ -590,8 +618,14 @@ void Viewport::draw(QGLPainter *painter) foreach (QObject *child, list) { QDeclarativeItem3D *item = qobject_cast<QDeclarativeItem3D *>(child); if (item) + { + if (d->showSceneGraph && (d->dumpCount == 0)) + qDumpItem(item); item->draw(painter); + } } + if (d->dumpCount >= 0) + --d->dumpCount; } /*! diff --git a/src/imports/threed/viewport.h b/src/imports/threed/viewport.h index 5a4c0f8d..f1844058 100644 --- a/src/imports/threed/viewport.h +++ b/src/imports/threed/viewport.h @@ -61,7 +61,8 @@ class Viewport : public QDeclarativeItem, public QDeclarativeViewport { Q_OBJECT Q_PROPERTY(bool picking READ picking WRITE setPicking NOTIFY viewportChanged) - Q_PROPERTY(bool showPicking READ showPicking WRITE setShowPicking NOTIFY viewportChanged) + Q_PROPERTY(bool showPicking READ showPicking WRITE setShowPicking NOTIFY viewportChanged) + Q_PROPERTY(bool showSceneGraph READ showSceneGraph WRITE setShowSceneGraph NOTIFY showSceneGraphChanged) Q_PROPERTY(bool navigation READ navigation WRITE setNavigation NOTIFY viewportChanged) Q_PROPERTY(bool fovzoom READ fovzoom WRITE setFovzoom NOTIFY viewportChanged) Q_PROPERTY(bool blending READ blending WRITE setBlending NOTIFY viewportChanged) @@ -78,6 +79,9 @@ public: bool showPicking() const; void setShowPicking(bool value); + bool showSceneGraph() const; + void setShowSceneGraph(bool show); + bool navigation() const; void setNavigation(bool value); @@ -105,6 +109,7 @@ public: Q_SIGNALS: void viewportChanged(); + void showSceneGraphChanged(); public Q_SLOTS: void update3d(); diff --git a/src/quick3d/qdeclarativeitem3d.cpp b/src/quick3d/qdeclarativeitem3d.cpp index ca886078..3e1af640 100644 --- a/src/quick3d/qdeclarativeitem3d.cpp +++ b/src/quick3d/qdeclarativeitem3d.cpp @@ -1387,6 +1387,45 @@ void QDeclarativeItem3D::drawItem(QGLPainter *painter) } } +/*! + \relates QDeclarativeItem3D + Print a description of \a item to the console. + + If \a detailed is true (which it is by default) then all the properties + of each node are printed. + + If \a detailed is false, then just one line is printed with the name and + some identifying information including a unique id for the node. + + The \a indent argument is used internally. +*/ +void qDumpItem(QDeclarativeItem3D *item, bool detailed, int indent) +{ + if (item) + { + QDeclarativeMesh *mesh = item->mesh(); + QString ind; + ind.fill(QLatin1Char(' '), indent * 4); + if (mesh) + { + QGLSceneNode *node = mesh->getSceneObject(); + if (node) + qDumpScene(node, detailed, indent + 1); + else + qDebug("%sMesh %p - %s (no node)", qPrintable(ind), mesh, qPrintable(mesh->objectName())); + } + else + { + qDebug("%sItem %p - %s (no mesh)", qPrintable(ind), item, qPrintable(item->objectName())); + } + QObjectList kids = item->children(); + for (int i = 0; i < kids.size(); ++i) + { + QDeclarativeItem3D *it = qobject_cast<QDeclarativeItem3D*>(kids.at(i)); + qDumpItem(it, detailed, indent + 1); + } + } +} /*! Calculates and returns a matrix that transforms local coordinates into diff --git a/src/quick3d/qdeclarativeitem3d.h b/src/quick3d/qdeclarativeitem3d.h index edd228e6..5d489543 100644 --- a/src/quick3d/qdeclarativeitem3d.h +++ b/src/quick3d/qdeclarativeitem3d.h @@ -217,6 +217,8 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeItem3D::CullFaces) QML_DECLARE_TYPE(QDeclarativeItem3D) +Q_QT3D_QUICK_EXPORT void qDumpItem(QDeclarativeItem3D *item, bool detailed = true, int indent = 0); + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/threed/scene/qglscenenode.cpp b/src/threed/scene/qglscenenode.cpp index 233f034e..545793fb 100644 --- a/src/threed/scene/qglscenenode.cpp +++ b/src/threed/scene/qglscenenode.cpp @@ -50,6 +50,11 @@ #include "qglabstracteffect.h" #include "qgraphicstransform3d.h" +#ifndef QT_NO_DEBUG_STREAM +#include "qglmaterialcollection.h" +#include "qgltexture2d.h" +#endif + #include <QtGui/qmatrix4x4.h> #if !defined(QT_NO_THREAD) #include <QtCore/qthread.h> @@ -1069,7 +1074,10 @@ QList<QGLSceneNode*> QGLSceneNode::allChildren() const Adds the \a node to the list of child nodes for this node. This function does nothing if \a node is null or is already a child - of this node. If the aim is to have the same geometry displayed several times under a + of this node. If the \a node is the node itself, a warning about an + attempt to add a node to itself is printed, and no add takes place. + + If the aim is to have the same geometry displayed several times under a given node, each time with different transformations, use the clone() call to create copies of the node and then apply the transformations to the copies. @@ -1104,7 +1112,8 @@ QList<QGLSceneNode*> QGLSceneNode::allChildren() const void QGLSceneNode::addNode(QGLSceneNode *node) { Q_D(QGLSceneNode); - if (!node || node->d_ptr->parentNodes.contains(this)) + bool alreadyAdded = node && node->d_ptr->parentNodes.contains(this); + if (!node || node == this || alreadyAdded) return; // Invalid node, or already under this parent. invalidateBoundingBox(); d->childNodes.append(node); @@ -1298,7 +1307,7 @@ void QGLSceneNode::drawGeometry(QGLPainter *painter) } /*! - Draws this scene node on the \a painter. + Draws this scene node and its children on the \a painter. In detail this function: \list @@ -1620,17 +1629,30 @@ QGLSceneNode *QGLSceneNode::only(const QStringList &names, QObject *parent) cons and QGLSceneNode::ReportCulling options are both set. */ -#ifndef QT_NO_DEBUG_STREAM -#include "qglmaterialcollection.h" -#include "qgltexture2d.h" /*! \relates QGLSceneNode - Print a description of \a node, and all its descendants, to stderr. Only - available when compiled in debug mode (without QT_NO_DEBUG defined). + Print a description of \a node, and all its descendants, to the console. + This function uses qDebug for its output, so in the case of Windows the + output will go to the debug window. If QT_NO_DEBUG_OUTPUT or QT_NO_DEBUG + has been defined, (as in release mode) this function will exit without + doing anything. + + If \a detailed is true (which it is by default) then all the properties + of each node are printed, including materials, geometry and transforms. + + If \a detailed is false, then just one line is printed with the name and + some identifying information including a unique id for the node. + The \a indent and \a loop parameters are used internally. */ -void qDumpScene(QGLSceneNode *node, int indent, const QSet<QGLSceneNode *> &loop) +void qDumpScene(QGLSceneNode *node, bool detailed, int indent, const QSet<QGLSceneNode *> &loop) { +#if defined(QT_NO_DEBUG_STREAM) || defined(QT_NO_DEBUG) || defined(QT_NO_DEBUG_OUTPUT) + Q_UNUSED(node); + Q_UNUSED(detailed); + Q_UNUSED(indent); + Q_UNUSED(loop); +#else #if !defined(QT_NO_THREAD) QCoreApplication *app = QApplication::instance(); QThread *appThread = 0; @@ -1641,108 +1663,124 @@ void qDumpScene(QGLSceneNode *node, int indent, const QSet<QGLSceneNode *> &loop lp.insert(node); QString ind; ind.fill(QLatin1Char(' '), indent * 4); - qWarning("\n%s ======== Node: %p - %s =========\n", qPrintable(ind), node, - qPrintable(node->objectName())); + if (detailed) + { + qDebug("\n%s ======== Node: %p - %s =========", qPrintable(ind), node, + qPrintable(node->objectName())); + } + else + { + qDebug("\n%s Node: %p - %s", qPrintable(ind), node, + qPrintable(node->objectName())); + return; + } #if !defined(QT_NO_THREAD) if (appThread && appThread != node->thread()) - qWarning("\n%s from thread: %p\n", qPrintable(ind), node->thread()); + qDebug("\n%s from thread: %p", qPrintable(ind), node->thread()); #endif - qWarning("%s start: %d count: %d children:", qPrintable(ind), node->start(), node->count()); + qDebug("%s start: %d count: %d children:", qPrintable(ind), node->start(), node->count()); { QList<QGLSceneNode*> children = node->children(); QList<QGLSceneNode*>::const_iterator it = children.constBegin(); for (int i = 0; it != children.constEnd(); ++it, ++i) - qWarning("%d: %p ", i, *it); + qDebug("%s %d: %p ", qPrintable(ind), i, *it); } - qWarning("\n"); if (!node->position().isNull()) { QVector3D p = node->position(); - qWarning("%s position: (%0.4f, %0.4f, %0.4f)\n", qPrintable(ind), + qDebug("%s position: (%0.4f, %0.4f, %0.4f)", qPrintable(ind), p.x(), p.y(), p.z()); } if (node->localTransform().isIdentity()) { - qWarning("%s local transform: identity\n", qPrintable(ind)); + qDebug("%s local transform: identity", qPrintable(ind)); } else { - qWarning("%s local transform:\n", qPrintable(ind)); + qDebug("%s local transform:", qPrintable(ind)); QMatrix4x4 m = node->localTransform(); for (int i = 0; i < 4; ++i) - qWarning("%s %0.4f %0.4f %0.4f %0.4f\n", + qDebug("%s %0.4f %0.4f %0.4f %0.4f", qPrintable(ind), m(i, 0), m(i, 1), m(i, 2), m(i, 3)); } + QList<QGraphicsTransform3D*> tx = node->transforms(); + if (tx.size() > 0) + qDebug("%s transforms list:", qPrintable(ind)); + for (int i = 0; i < tx.size(); ++i) + { + const QMetaObject *obj = tx.at(i)->metaObject(); + qDebug("%s %s", qPrintable(ind), obj->className()); + } if (!node->geometry().isEmpty()) { - qWarning("%s geometry: %d indexes, %d vertices\n", + qDebug("%s geometry: %d indexes, %d vertices", qPrintable(ind), node->geometry().count(), node->geometry().count(QGL::Position)); } else { - qWarning("%s geometry: NULL\n", qPrintable(ind)); + qDebug("%s geometry: NULL", qPrintable(ind)); } if (node->materialIndex() != -1) { - qWarning("%s material: %d", qPrintable(ind), node->materialIndex()); + qDebug("%s material: %d", qPrintable(ind), node->materialIndex()); QGLMaterial *mat = node->material(); QGLMaterialCollection *pal = node->palette(); if (pal) - qWarning("%s palette: %p", qPrintable(ind), pal); + qDebug("%s palette: %p", qPrintable(ind), pal); else - qWarning("%s no palette", qPrintable(ind)); + qDebug("%s no palette", qPrintable(ind)); if (pal) { mat = pal->material(node->materialIndex()); if (mat) - qWarning("%s mat name from pal: %s ", qPrintable(ind), + qDebug("%s mat name from pal: %s ", qPrintable(ind), qPrintable(pal->material(node->materialIndex())->objectName())); else - qWarning("%s indexed material %d does not exist in palette!", + qDebug("%s indexed material %d does not exist in palette!", qPrintable(ind), node->materialIndex()); } if (mat) { + QString mat_spx = QString(QLatin1String(" Amb: %1 - Diff: %2 - Spec: %3 - Shin: %4")) + .arg((mat->ambientColor().name())) + .arg(mat->diffuseColor().name()) + .arg(mat->specularColor().name()) + .arg(mat->shininess()); if (mat->objectName().isEmpty()) - qWarning(" -- %p:", mat); + qDebug("%s material pointer %p: %s", qPrintable(ind), mat, qPrintable(mat_spx)); else - qWarning(" -- \"%s\":", - qPrintable(mat->objectName())); - qWarning(" Amb: %s - Diff: %s - Spec: %s - Shin: %0.2f\n", - qPrintable(mat->ambientColor().name()), - qPrintable(mat->diffuseColor().name()), - qPrintable(mat->specularColor().name()), - mat->shininess()); + qDebug("%s \"%s\": %s", qPrintable(ind), + qPrintable(mat->objectName()), qPrintable(mat_spx)); for (int i = 0; i < mat->textureLayerCount(); ++i) { if (mat->texture(i) != 0) { QGLTexture2D *tex = mat->texture(i); if (tex->objectName().isEmpty()) - qWarning("%s texture %p", qPrintable(ind), tex); + qDebug("%s texture %p", qPrintable(ind), tex); else - qWarning("%s texture %s", qPrintable(ind), + qDebug("%s texture %s", qPrintable(ind), qPrintable(tex->objectName())); QSize sz = tex->size(); - qWarning(" - size: %d (w) x %d (h)\n", sz.width(), sz.height()); + qDebug(" - size: %d (w) x %d (h)", sz.width(), sz.height()); } } } else { - qWarning("%s - could not find indexed material!!", qPrintable(ind)); + qDebug("%s - could not find indexed material!!", qPrintable(ind)); } } else { - qWarning("%s material: NONE\n", qPrintable(ind)); + qDebug("%s material: NONE", qPrintable(ind)); } if (node->hasEffect()) { if (node->userEffect()) { - qWarning("%s user effect %p\n", qPrintable(ind), + qDebug("%s user effect %p", qPrintable(ind), node->userEffect()); } else @@ -1750,33 +1788,35 @@ void qDumpScene(QGLSceneNode *node, int indent, const QSet<QGLSceneNode *> &loop switch (node->effect()) { case QGL::FlatColor: - qWarning("%s flat color effect\n", qPrintable(ind)); break; + qDebug("%s flat color effect", qPrintable(ind)); break; case QGL::FlatPerVertexColor: - qWarning("%s flat per vertex color effect\n", qPrintable(ind)); break; + qDebug("%s flat per vertex color effect", qPrintable(ind)); break; case QGL::FlatReplaceTexture2D: - qWarning("%s flat replace texture 2D effect\n", qPrintable(ind)); break; + qDebug("%s flat replace texture 2D effect", qPrintable(ind)); break; case QGL::FlatDecalTexture2D: - qWarning("%s flat decal texture 2D effect\n", qPrintable(ind)); break; + qDebug("%s flat decal texture 2D effect", qPrintable(ind)); break; case QGL::LitMaterial: - qWarning("%s lit material effect\n", qPrintable(ind)); break; + qDebug("%s lit material effect", qPrintable(ind)); break; case QGL::LitDecalTexture2D: - qWarning("%s lit decal texture 2D effect\n", qPrintable(ind)); break; + qDebug("%s lit decal texture 2D effect", qPrintable(ind)); break; case QGL::LitModulateTexture2D: - qWarning("%s lit modulate texture 2D effect\n", qPrintable(ind)); break; + qDebug("%s lit modulate texture 2D effect", qPrintable(ind)); break; } } } else { - qWarning("%s no effect set\n", qPrintable(ind)); + qDebug("%s no effect set", qPrintable(ind)); } QList<QGLSceneNode*> children = node->children(); QList<QGLSceneNode*>::const_iterator it = children.constBegin(); for ( ; it != children.constEnd(); ++it) if (!lp.contains(*it)) qDumpScene(*it, indent + 1); +#endif } +#ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QGLSceneNode &node) { dbg << &node << "\n start:" << node.start() << " count:" << node.count(); @@ -1839,6 +1879,6 @@ QDebug operator<<(QDebug dbg, const QGLSceneNode &node) return dbg; } -#endif +#endif // QT_NO_DEBUG_STREAM QT_END_NAMESPACE diff --git a/src/threed/scene/qglscenenode.h b/src/threed/scene/qglscenenode.h index 6156a4d9..edf08874 100644 --- a/src/threed/scene/qglscenenode.h +++ b/src/threed/scene/qglscenenode.h @@ -192,9 +192,9 @@ private: Q_DECLARE_OPERATORS_FOR_FLAGS(QGLSceneNode::Options) -#ifndef QT_NO_DEBUG_STREAM -Q_QT3D_EXPORT void qDumpScene(QGLSceneNode *, int indent = 0, const QSet<QGLSceneNode*> &loop = QSet<QGLSceneNode*>()); +Q_QT3D_EXPORT void qDumpScene(QGLSceneNode *, bool detailed = true, int indent = 0, const QSet<QGLSceneNode*> &loop = QSet<QGLSceneNode*>()); +#ifndef QT_NO_DEBUG_STREAM Q_QT3D_EXPORT QDebug operator<<(QDebug dbg, const QGLSceneNode &node); #endif |