Как нарисовать функциональную кривую в qt3d? - PullRequest
1 голос
/ 16 февраля 2020

Я пытаюсь изучить Qt3D, и у меня проблема с рисованием кривых. После нескольких попыток я использовал точечный рендеринг, как здесь ( Как нарисовать простую линию в Qt3D? ), но хранить все точки в памяти слишком дорого. Я попытался соединить точки линиями по очереди, и мне это удалось, но он все еще работает слишком медленно для больших значений. Есть ли способ сделать это с помощью 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);
}

...