使用Qt3D API绘制一个三角形

使用Qt3D API, 不通过qml创建一个三角形

 

开发环境:vs2019 +  qt 6.1 ,如果用qt5,包名可能不同

新建项目,使用Qt Widgets Appliction向导

项目名 Qt3dDrawTriangle, Qt Modules增加3d

打开Qt3dDrawTriangle.cpp替换为以下代码,F5运行即可看到一个红色三角形

#include "Qt3dDrawTriangle.h"

#include <Qt3DRender/qrenderaspect.h>
#include <Qt3DExtras/qforwardrenderer.h>
#include <QtGui/QScreen>
#include <Qt3DExtras/qt3dwindow.h>
#include <Qt3DRender/QGeometryRenderer>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qtransform.h>
#include <Qt3DCore/QEntity>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QCameraLens>
#include <Qt3DCore/QTransform>
#include <Qt3DCore/QAspectEngine>
#include <Qt3DRender/QPointLight>
#include <Qt3DRender/QDirectionalLight>
#include <Qt3DRender/QSpotLight>

#include <Qt3DCore/QBuffer>
#include <Qt3DCore/QGeometry>
#include <Qt3DCore/QAttribute>

#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DExtras/QOrbitCameraController>


Qt3DCore::QAttribute* buildAttribute(const QString& name, const float* data, int vertexSize, int count) {
    QByteArray bufferBytes;
    bufferBytes.resize(vertexSize * count * sizeof(float));
    float* p = reinterpret_cast<float*>(bufferBytes.data());
    for (int i = 0; i < vertexSize * count; ++i) {
        *p++ = *data++;
    }

    auto* attr = new Qt3DCore::QAttribute();
    auto* buf = new Qt3DCore::QBuffer(attr);
    buf->setData(bufferBytes);
    attr->setBuffer(buf);

    attr->setName(name);
    attr->setVertexBaseType(Qt3DCore::QAttribute::Float);
    attr->setVertexSize(vertexSize);
    attr->setAttributeType(Qt3DCore::QAttribute::VertexAttribute);
    attr->setByteStride(vertexSize * sizeof(float));
    attr->setCount(count);
    return attr;
}

Qt3DCore::QAttribute* buildIndexAttribute(const unsigned int* indices, int count) {
    QByteArray bytes;
    bytes.resize(count * sizeof(unsigned int)); // 这里用的32位索引,根据需要可使用16位
    unsigned int* data = reinterpret_cast<unsigned int*>(bytes.data());
    for (int i = 0; i < count; ++i) {
        *data++ = *indices++;
    }

    auto* indexBuffer = new Qt3DCore::QBuffer();
    indexBuffer->setData(bytes);
    auto* attr = new Qt3DCore::QAttribute();
    attr->setVertexBaseType(Qt3DCore::QAttribute::UnsignedInt);
    attr->setAttributeType(Qt3DCore::QAttribute::IndexAttribute);
    attr->setBuffer(indexBuffer);
    attr->setCount(count);
    return attr;
}

Qt3dDrawTriangle::Qt3dDrawTriangle(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

    Qt3DExtras::Qt3DWindow* view = new Qt3DExtras::Qt3DWindow();
    view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x4d4d4f)));
    QWidget* container = QWidget::createWindowContainer(view);
    QSize screenSize = view->screen()->size();
    container->setMinimumSize(QSize(200, 100));
    container->setMaximumSize(screenSize);

    this->setCentralWidget(container);

    // Root entity
    Qt3DCore::QEntity* rootEntity = new Qt3DCore::QEntity();

    // Camera
    Qt3DRender::QCamera* camera = view->camera();
    camera->lens()->setPerspectiveProjection(45.0f, 16.0f / 9.0f, 0.1f, 1000.0f);
    camera->setPosition(QVector3D(0, 0, 10.0f));
    camera->setViewCenter(QVector3D(0, 0, 0));

    Qt3DExtras::QOrbitCameraController* camController = new Qt3DExtras::QOrbitCameraController(rootEntity);
    camController->setCamera(camera);
    
    auto* geometry = new Qt3DCore::QGeometry(rootEntity);
    float pos[] = { 0,0,0,  1,0,0, 0,1,0 };
    float uv[] = { 0,0,  1,0, 0,1 };
    float normal[] = { 0,0,1,  0,0,1, 0,0,1 };
    unsigned int indices[] = { 0,1,2 };
    geometry->addAttribute(buildAttribute(Qt3DCore::QAttribute::defaultPositionAttributeName(), pos, 3, 3));
    //geometry->addAttribute(buildAttribute(Qt3DCore::QAttribute::defaultTextureCoordinateAttributeName(), uv, 2, 3));
    geometry->addAttribute(buildAttribute(Qt3DCore::QAttribute::defaultNormalAttributeName(), normal, 3, 3));
    geometry->addAttribute(buildIndexAttribute(indices, 3));

    Qt3DRender::QGeometryRenderer* gr = new Qt3DRender::QGeometryRenderer(rootEntity);
    gr->setGeometry(geometry);
    gr->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles);

    Qt3DCore::QEntity* entity = new Qt3DCore::QEntity(rootEntity);
    Qt3DCore::QTransform* transform = new Qt3DCore::QTransform;
    transform->setScale3D(QVector3D(5, 5, 5));
    transform->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), 0.0f));
    auto* material = new Qt3DExtras::QPhongMaterial(rootEntity);
    //material->setDiffuse(QColor(QRgb(0xffffff)));
    material->setAmbient(QColor(QRgb(0xff0000)));

    entity->addComponent(gr);
    entity->addComponent(transform);
    entity->addComponent(material);

    view->setRootEntity(rootEntity);
}

说明:

QT场景节点为:QEntity,下面可以挂接 QGeometryRenderer(网格数据), QTransform(位置),QMaterial(材质)
QGeometryRenderer 内含QGeometry(顶点数据,各种顶点Buffer)


其中稍微麻烦点是生成顶点属性: buildAttribute,顶点索引buildIndexAttribute实现类似

个人感觉Qt3d还不够成熟,官方也没有什么开发资料,不适合使用
posted @ 2021-05-17 17:03  wiki3D  阅读(817)  评论(0编辑  收藏  举报