Qt3D: QGLMaterial / QGLMaterialCollection: large scene about 1000 Objects + 1000 QGLMaterials
-
I use Qt3D for my thesis. The scene consists of the 1500 spheres and 1000 the cylinders. The different color must be set for each sphere and cylinder. I use a QGLCollectionMaterial, create n of QGLMaterial-Object and add material to Collection. For each QGLSceneNode (sphere or cylinder) i set a palette - MaterialCollection and then call setMaterialIndex(i), where i is corresponding index. With n = 25 (Material count) and 2000 of QGLSceneNodes , the scene is rendered, but a little slow responding to the mouse manipulation (rotate, zoom). A further increase in number of colors is the scene even less interactive, and with n = 100 it looks like a slideshow. In my example, instead of the color QGLMaterial includes the texture, but that does not matter. The same happens if the color is set. I modified the example of qt3d/src/examples/qt3d/builder. Below is a source code:
Header File:
@#ifndef BUILDER_H
#define BUILDER_H
#include "qglview.h"QT_BEGIN_NAMESPACE
class QGLSceneNode;
class QGLBuilder;
QT_END_NAMESPACE
class BuilderView : public QGLView
{
Q_OBJECT
public:
BuilderView(const QGLFormat &f, QWidget *parent = 0);
~BuilderView();
protected:
void initializeGL(QGLPainter *painter);
void paintGL(QGLPainter *painter);
private:
QGLSceneNode *buildGeometry();
QGLSceneNode *buildGeometry2(qreal radius = 1.0, int divisions = 5);
QGLSceneNode *canScene;
int mCount;
int mColorCount;
QGLMaterialCollection *mPalette;
void initializePalette();
};
#endif@Cpp-file:
@#include "builder.h"
#include "qglbuilder.h"
#include "qglmaterialcollection.h"
#include "qgltexture2d.h"
#include "qglmaterial.h"
#include "qglscenenode.h"
#include "qgllightmodel.h"
#include "qglsphere.h"
#include "qglcylinder.h"
#include <QtGui/qmatrix4x4.h>
#include <QtCore/qmath.h>static inline qreal rval()
{
return qreal((qreal(qrand()) / qreal(RAND_MAX)) * 200.0);
}static inline int ival()
{
return (qreal(qrand()) / qreal(RAND_MAX)) * 255;
}BuilderView::BuilderView(const QGLFormat &f, QWidget *parent)
: QGLView(f, parent)
, canScene(new QGLSceneNode(this))
{
QGLSceneNode *can = buildGeometry();
//QGLSceneNode *sphere = buildGeometry2();
mPalette = new QGLMaterialCollection(canScene);
mCount = 1000;
mColorCount = 100;
initializePalette();
can->setObjectName("SceneNode Can");
canScene->setObjectName("Root - canScene");
for(int i = 1; i < mCount; i++)
{
QGLSceneNode *node = new QGLSceneNode(canScene);
node->setObjectName("Sphere_r_" + QString::number(i));
node->setPalette(mPalette);
node->setMaterialIndex(i % mColorCount);;
node->setEffect(QGL::LitModulateTexture2D);
node->addNode(can);
{
QMatrix4x4 mat;
mat.translate(1.0f * rval(), 1.0f * rval(), -1.0f * rval());
node->setLocalTransform(mat);
}
node = new QGLSceneNode(canScene);
node->setObjectName("Sphere_b_" + QString::number(i));
node->setPalette(mPalette);
node->setMaterialIndex(i % mColorCount);
node->setEffect(QGL::LitModulateTexture2D);
node->addNode(can);
{
QMatrix4x4 mat;
mat.translate(-1.0f * rval(), -1.0f * rval(), -1.0f * rval());
node->setLocalTransform(mat);
}
}
}BuilderView::~BuilderView()
{
delete canScene;
}void BuilderView::initializeGL(QGLPainter *painter)
{
glEnable(GL_CULL_FACE);
camera()->setFieldOfView(45);
camera()->setNearPlane(0.1);
camera()->setFarPlane(5000);
camera()->setEye(QVector3D(0.0, 0.0, 100.0));
}void BuilderView::paintGL(QGLPainter *painter)
{
canScene->draw(painter);
}QGLSceneNode *BuilderView::buildGeometry()
{
QGLBuilder builder;
builder << QGLCylinder(1.0f, 1.0f, 5.0f, 32);
return builder.finalizedSceneNode();
}QGLSceneNode *BuilderView::buildGeometry2(qreal radius, int divisions)
{
QGLBuilder builder;
builder << QGLSphere(radius, divisions);
return builder.finalizedSceneNode();
}void BuilderView::initializePalette()
{
for(int i = 0; i < mColorCount; i++)
{
QImage image(QSize(1, 6), QImage::Format_ARGB32_Premultiplied);
QPainter painter(&image);
QColor c(ival(), ival(), ival());
QColor c2(ival(), ival(), ival());
QLinearGradient linearGrad(QPointF(0.5, 0), QPointF(0.5, 6));
linearGrad.setColorAt(0, c);
linearGrad.setColorAt(1, c2);
painter.fillRect(image.rect(), linearGrad);
painter.end();
QGLMaterial *m = new QGLMaterial;
//m->setColor(c);
QGLTexture2D *tex = new QGLTexture2D(m);
tex->setImage(image);
m->setTexture(tex);
mPalette->addMaterial(m);
}
}@With a few manipulations can reproduce several cases: e.g. add color or texture to the material, change the number of objects, change the number of colors / materials, etc. The dependency that I have noticed is the number of materials in the collection + number of QGLScenenodes. I've done a few tests with the other example "tank" under qt3d/examples/qt3d. There the scene is less interactive with the number of tank-objects from 250-300. This case can you self produce with 200 times DoubleClick. )))
Summary: is a bug in Qt3D or anybody have a ide, how to put or to manage a large amount of colors / materials for several QGLScenenodes. And under "several QGLScenenodes" i understand more than 2000 objects.
My thesis software looks of course different, but the idea is the same. And maybe one preliminary question: if it is possible to use/set several colors to multiple objects in the scene, then I can change the color easily in runtime?