• 使用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还不够成熟,官方也没有什么开发资料,不适合使用
  • 相关阅读:
    多组件共享-vuex
    在子组件中触发事件,传值给父组件-vue
    在父组件中,直接获取子组件数据-vue
    非父子组件通过事件传值-vue
    在父组件中,传值给子组件-vue
    MVVM
    Virtual DOM-渲染函数render -vue
    duilib入门简明教程 -- VS环境配置(2) (转)
    duilib入门简明教程 -- 前言(1) (转)
    【CDockablePane】关于CDockablePane
  • 原文地址:https://www.cnblogs.com/wiki3d/p/qt3d.html
Copyright © 2020-2023  润新知