summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSarah Smith <sarah.j.smith@nokia.com>2011-11-27 14:16:04 -0800
committerQt by Nokia <qt-info@nokia.com>2011-12-01 05:24:02 +0100
commit6502c4da8a725d6bf908266826b00fa2862ca1ee (patch)
treee9ecf799edf9e45843100a4a5791b9ec2dca5769
parentd6a188c6136c33b5079878529d425c0d39d17fe1 (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.cpp34
-rw-r--r--src/imports/threed/viewport.h7
-rw-r--r--src/quick3d/qdeclarativeitem3d.cpp39
-rw-r--r--src/quick3d/qdeclarativeitem3d.h2
-rw-r--r--src/threed/scene/qglscenenode.cpp138
-rw-r--r--src/threed/scene/qglscenenode.h4
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