Qt qml 3D Render

Qt qml 3D Render

main.cpp

//main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "triangleitem.h"

int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

    QGuiApplication app(argc, argv);

    qmlRegisterType< TriangleItem >("Shapes", 1, 0, "Triangle");

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
        &app, [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

main.qml

//main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import Shapes 1.0

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Rectangle{
        anchors.fill: parent
        Triangle{
            id: d3DRenderer
            anchors.fill: parent
            anchors.margins: 100
        }

        Text{
            text: "3D & qml"
            font.pixelSize: 48
            font.bold: true
            color: "black"
            anchors.bottom: d3DRenderer.bottom
            anchors.horizontalCenter: d3DRenderer.horizontalCenter
        }
    }
}


triangleitem.h

//triangleitem.h
#ifndef TRIANGLEITEM_H
#define TRIANGLEITEM_H

#include <QQuickItem>
#include <QQuickPaintedItem>

class TriangleItem : public QQuickItem
{
    Q_OBJECT

public:
    TriangleItem(QQuickItem* parent = 0);
    QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;

protected slots:
    void updateColors();

private:
    float m_colorHue;

};

#endif // TRIANGLEITEM_H

triangleitem.cpp

//triangleitem.cpp
#include "triangleitem.h"

#include <QPainter>
#include <QSGFlatColorMaterial>
#include <QSGGeometryNode>
#include <QSGVertexColorMaterial>
#include <QTimer>

#include <QDebug>

TriangleItem::TriangleItem(QQuickItem *parent)
    : QQuickItem( parent )
{
    setFlag(QQuickItem::ItemHasContents, true);

    QTimer *timer = new QTimer( this );
    connect(timer, &QTimer::timeout, this, &TriangleItem::updateColors);
    timer->start(16);
}

void TriangleItem::updateColors()
{
    m_colorHue += 0.5f;
    m_colorHue = fmod(m_colorHue, 360.0f);

    update();
}

// HSV2RGB assuming S and V to be 1
static QRgb hue2rgb(float hue)
{
    hue = fmod(hue, 360.0f);
    hue /= 60.0f;
    const int i = int(hue);

    hue = 1.0f - fabs(fmod(hue, 2.0f) - 1.0f);
    const int h = int(hue * 255);

    switch (i) {
    case 0:
        return qRgb(255, h, 0);
    case 1:
        return qRgb(h, 255, 0);
    case 2:
        return qRgb(0, 255, h);
    case 3:
        return qRgb(0, h, 255);
    case 4:
        return qRgb(h, 0, 255);
    case 5:
        return qRgb(255, 0, h);
    }

    return QRgb(0);
}

QSGNode *TriangleItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
    if(width() <= 0 || height() <=0){
        delete oldNode;
        return 0;
    }

    QSGNode *rootNode = static_cast< QSGNode* >( oldNode );
    QSGTransformNode *transformNode;
    QSGGeometryNode *triangleNode;

    //parent/child organization is: rootNode -> transformNode -> trangleNode
    if( Q_LIKELY(rootNode) ){
        transformNode = static_cast< QSGTransformNode* >(rootNode->firstChild());
        triangleNode = static_cast< QSGGeometryNode* >(transformNode->firstChild());
    }else{
        rootNode = new QSGNode;

        transformNode = new QSGTransformNode;
        transformNode->setFlag(QSGNode::OwnedByParent, true);
        rootNode->appendChildNode(transformNode);

        triangleNode = new QSGGeometryNode;
        triangleNode->setFlag(QSGNode::OwnedByParent, true);
        triangleNode->setFlag(QSGNode::OwnsGeometry, true);
        triangleNode->setFlag(QSGNode::OwnsOpaqueMaterial, true);
        QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 3);
        triangleNode->setGeometry( geometry );

        QSGVertexColorMaterial *material = new QSGVertexColorMaterial;
        triangleNode->setMaterial( material );

        transformNode->appendChildNode(triangleNode);
    }

    // rotate the triangle around the center of the item
    QMatrix4x4 rotationMatrix;
    rotationMatrix.translate(width() / 2, height() / 2);
    rotationMatrix.rotate(m_colorHue, QVector3D(0, 0, 1));
    rotationMatrix.translate(-width() / 2, -height() / 2);
    transformNode->setMatrix(rotationMatrix);
    transformNode->markDirty(QSGNode::DirtyMatrix);

    QSGGeometry::ColoredPoint2D *points = triangleNode->geometry()->vertexDataAsColoredPoint2D();

    QRgb color = hue2rgb(m_colorHue);

    points[0].x = 0;
    points[0].y = height();
    points[0].r = qRed(color);
    points[0].g = qGreen(color);
    points[0].b = qBlue(color);
    points[0].a = qAlpha(color);

    color = hue2rgb(m_colorHue + 120);

    points[1].x = width();
    points[1].y = height();
    points[1].r = qRed(color);
    points[1].g = qGreen(color);
    points[1].b = qBlue(color);
    points[1].a = qAlpha(color);

    color = hue2rgb(m_colorHue + 240);

    points[2].x = width() / 2.0f;
    points[2].y = 0;
    points[2].r = qRed(color);
    points[2].g = qGreen(color);
    points[2].b = qBlue(color);
    points[2].a = qAlpha(color);

    // tell QSGGeometry it needs to reupload vertex data
    triangleNode->geometry()->markVertexDataDirty();

    //tell the QSGNode to trigger a geometry update ( which will see the vertex data marked as dirty)
    triangleNode->markDirty(QSGNode::DirtyGeometry);

    return rootNode;
}

效果:

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一个比较复杂的工程,需要涉及到QT QML的3D图形绘制和数学计算。以下是一个简单的示例代码,可以用来实现3D模型的运动和轨迹图绘制: ``` import Qt3D.Core 2.12 import Qt3D.Render 2.12 import Qt3D.Input 2.12 import Qt3D.Extras 2.12 Entity { id: root property real speed: 1 // 模型运动速度 property real timeStep: 0.01 // 时间步长 property int numPoints: 1000 // 轨迹图上的点数 property real pointSize: 0.1 // 轨迹图上的点的大小 // 定义模型和轨迹图的材质 Material { id: material effect: Effect { techniques: Technique { graphicsApiFilter { api: GraphicsApiFilter.OpenGL profile: GraphicsApiFilter.CoreProfile majorVersion: 3 minorVersion: 2 } renderPasses: RenderPass { shaderProgram: ShaderProgram { vertexShaderCode: loadSource("qrc:/vertex.glsl") fragmentShaderCode: loadSource("qrc:/fragment.glsl") } } } } } // 定义模型 Entity { id: model // 模型的网格 Mesh { id: mesh source: "qrc:/model.obj" } // 模型的变换 Transform { id: transform translation: Qt.vector3d(0, 0, 0) // 初始位置 rotation: Qt.vector3d(0, 0, 0) // 初始旋转 scale: Qt.vector3d(1, 1, 1) // 初始缩放 } // 模型的渲染器 RenderableMesh { mesh: mesh material: material primitiveType: RenderableMesh.Triangles } } // 定义轨迹图 Entity { id: trajectory // 轨迹图的网格 Mesh { id: mesh vertexCount: numPoints attribute: VertexAttribute { name: "position" vertexBaseType: VertexAttribute.Float vertexSize: 3 byteOffset: 0 byteStride: 12 divisor: 0 buffer: Buffer { id: buffer type: Buffer.VertexBuffer data: Float32Array(numPoints * 3) } } attribute: VertexAttribute { name: "color" vertexBaseType: VertexAttribute.Float vertexSize: 3 byteOffset: 0 byteStride: 12 divisor: 0 buffer: Buffer { id: buffer type: Buffer.VertexBuffer data: Float32Array(numPoints * 3) } } } // 轨迹图的变换 Transform { id: transform translation: Qt.vector3d(0, 0, 0) // 初始位置 rotation: Qt.vector3d(0, 0, 0) // 初始旋转 scale: Qt.vector3d(1, 1, 1) // 初始缩放 } // 轨迹图的渲染器 RenderableMesh { mesh: mesh material: material primitiveType: RenderableMesh.Points pointSize: pointSize } } // 定义计时器,用于更新模型和轨迹图的位置 Timer { id: timer interval: timeStep * 1000 // 每个时间步长更新一次 running: true repeat: true onTriggered: { // 更新模型位置 model.transform.translation = Qt.vector3d( model.transform.translation.x + speed * timeStep, model.transform.translation.y, model.transform.translation.z ) // 更新轨迹图位置 var position = trajectory.mesh.attributeByIndex(0).buffer.data var color = trajectory.mesh.attributeByIndex(1).buffer.data for (var i = numPoints - 1; i > 0; i--) { position[i*3] = position[(i-1)*3] position[i*3+1] = position[(i-1)*3+1] position[i*3+2] = position[(i-1)*3+2] color[i*3] = color[(i-1)*3] color[i*3+1] = color[(i-1)*3+1] color[i*3+2] = color[(i-1)*3+2] } position[0] = model.transform.translation.x position[1] = model.transform.translation.y position[2] = model.transform.translation.z color[0] = 1 color[1] = 0 color[2] = 0 trajectory.mesh.attributeByIndex(0).buffer.data = position trajectory.mesh.attributeByIndex(1).buffer.data = color } } } ``` 其中,`model`代表3D模型,`trajectory`代表轨迹图。`material`是模型和轨迹图的共用材质,`speed`是模型的运动速度,`timeStep`是时间步长,`numPoints`是轨迹图上的点数,`pointSize`是轨迹图上的点的大小。`timer`是计时器,用于更新模型和轨迹图的位置。 在实际使用中,需要将示例代码中的模型、材质、着色器和计算方法替换为自己的实现。同时,需要将模型的初始位置、旋转和缩放,以及轨迹图的初始位置、旋转和缩放设置为合适的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值