使用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还不够成熟,官方也没有什么开发资料,不适合使用