I am trying to learn Qt3D and I have a problem with drawing curves. After several attempts, I used point-by-point rendering as here(How do I draw a simple line in Qt3D?), but it is too expensive to store all points in memory. I tried to connect the points with lines in turn , and I succeeded, but it still works too slowly for large values. Is there a way to do this using Qt3D?
#include <QGuiApplication>
#include <Qt3DCore/QEntity>
#include <Qt3DCore/QTransform>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DExtras/QOrbitCameraController>
#include <Qt3DRender/QAttribute>
#include <Qt3DRender/QBuffer>
#include <Qt3DRender/QGeometry>
#include <Qt3DRender/QGeometryRenderer>
#include <Qt3DRender/QCamera>
#include <QtMath>
void drawSimpleLine(const QVector3D& start, const QVector3D& end, const QColor& color, Qt3DCore::QEntity *rootEntity);
void drawCurve(float start, float end, float step, const QColor& color, Qt3DCore::QEntity *rootEntity);
float Func(float x);
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);
Qt3DExtras::Qt3DWindow view;
auto *rootEntity = new Qt3DCore::QEntity;
auto *camera = view.camera();
camera->lens()->setPerspectiveProjection(60.0f, (float)view.width() / view.height(), 0.1f ,1000.0f);
camera->setPosition(QVector3D(0.0f, 0.0f, 100.0f));
camera->setViewCenter(QVector3D(0.0f, 0.0f, 0.0f));
auto *cameraController = new Qt3DExtras::QOrbitCameraController(rootEntity);
cameraController->setCamera(camera);
cameraController->setLookSpeed(180.0f);
cameraController->setLinearSpeed(60.0f);
view.setRootEntity(rootEntity);
view.show();
drawCurve(-200.0f,2000.0f,0.01f,QColor(255,0,0),rootEntity);
return a.exec();
}
float Func(float x)
{
return 4*qCos(x);
}
void drawCurve(float start, float end, float step, const QColor& color, Qt3DCore::QEntity *rootEntity)
{
float x = start;
while (x <= end - step)
{
drawSimpleLine(QVector3D(x,Func(x),0.0f),QVector3D(x+step, Func(x+step),0.0f),color,rootEntity);//point-by-point rendering
x += step;
}
}
//stackoverflow example
void drawSimpleLine(const QVector3D& start, const QVector3D& end, const QColor& color, Qt3DCore::QEntity *_rootEntity)
{
auto *geometry = new Qt3DRender::QGeometry(_rootEntity);
//verticles
QByteArray bufferBytes;
bufferBytes.resize(3 * 2 * sizeof(float));
float *positions = reinterpret_cast<float*>(bufferBytes.data());
*positions++ = start.x();
*positions++ = start.y();
*positions++ = start.z();
*positions++ = end.x();
*positions++ = end.y();
*positions++ = end.z();
auto *buf = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, geometry);
buf->setData(bufferBytes);
auto *positionAttribute = new Qt3DRender::QAttribute(geometry);
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
positionAttribute->setVertexSize(3);
positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
positionAttribute->setBuffer(buf);
positionAttribute->setByteStride(3 * sizeof(float));
positionAttribute->setCount(2);
geometry->addAttribute(positionAttribute); // adding in the geometry
// connectivity between vertices
QByteArray indexBytes;
indexBytes.resize(2 * sizeof(unsigned int));
unsigned int *indices = reinterpret_cast<unsigned int*>(indexBytes.data());
*indices++ = 0;
*indices++ = 1;
auto *indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, geometry);
indexBuffer->setData(indexBytes);
auto *indexAttribute = new Qt3DRender::QAttribute(geometry);
indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt);
indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
indexAttribute->setBuffer(indexBuffer);
indexAttribute->setCount(2);
geometry->addAttribute(indexAttribute); // We add the indices linking the points in the geometry
// mesh
auto *line = new Qt3DRender::QGeometryRenderer(_rootEntity);
line->setGeometry(geometry);
line->setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines);
auto *material = new Qt3DExtras::QPhongMaterial(_rootEntity);
material->setAmbient(color);
// entity
auto *lineEntity = new Qt3DCore::QEntity(_rootEntity);
lineEntity->addComponent(line);
lineEntity->addComponent(material);
}