使用Qt3D绘制机械手场景

1.前言

之前是使用Coin3D来绘制机械手场景的【Qt利用Coin3D(OpenInventor)进行3d绘图】
后来需要在HarmonyOS显示这个机械手模型,但是想要编译Coin3D到HarmonyOS的话,显然太难了。
然后尝试使用OpenGL原生的函数来绘制,但是HarmonyOS对很多函数都不支持,一查,发现HarmonyOS支持OpenglES。那就麻烦了。
最后,一番兜兜转转,还是用回Qt3D吧。

2.效果

效果也还行,但是某些功能还得研究一下。
在这里插入图片描述点、线、面、灯光等各种功能都ok。
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/8c52fb4533714e9588d87d3ac7d45ca5.png在这里插入图片描述

3.实现过程

主要是参考了Qt自带的例程以及网上的一些资料。

3.1.场景代码

在这里插入图片描述

3.2.自定义模型的渲染

【Qt3DExample】

3.3.绘制直线或者网格

【how-do-i-draw-a-simple-line-in-Qt3D】

int drawOriginGrid(const int rows,
                   const int cols,
                   const float step,
                   const QColor& color,
                   Qt3DCore::QEntity *_rootEntity)
{
    auto *geometry = new Qt3DRender::QGeometry(_rootEntity);

    QList<QVector3D> vertexList;
    // 横线
    for(int i = -rows; i <= rows; i++)
    {
        vertexList << QVector3D(cols  * step, 0, i * step);
        vertexList << QVector3D(-cols * step, 0, i * step);
    }
    // 竖线
    for(int i = -cols; i <= cols; i++)
    {
        vertexList << QVector3D(i * step, 0, rows * step);
        vertexList << QVector3D(i * step, 0, -rows * step);
    }
    QByteArray bufferBytes;
    bufferBytes.resize(3 * vertexList.length() * sizeof(float));
    float *positions = reinterpret_cast<float*>(bufferBytes.data());

    for(int i = 0; i < vertexList.length(); i++)
    {
        QVector3D vertex = vertexList.at(i);
        *positions++ = vertex.x();
        *positions++ = vertex.y();
        *positions++ = vertex.z();
    }

    auto *buf = new Qt3DRender::QBuffer(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(vertexList.length());
    geometry->addAttribute(positionAttribute); // We add the vertices in the geometry

    // connectivity between vertices
    QByteArray indexBytes;
    indexBytes.resize(2 * vertexList.length() * sizeof(unsigned int));
    unsigned int *indices = reinterpret_cast<unsigned int*>(indexBytes.data());
    for(int i = 0; i < vertexList.length(); i++)
    {
        *indices++ = i;
    }

    auto *indexBuffer = new Qt3DRender::QBuffer(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(vertexList.length());
    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);
    material->setDiffuse(color);

    // entity
    auto *lineEntity = new Qt3DCore::QEntity(_rootEntity);
    lineEntity->addComponent(line);
    lineEntity->addComponent(material);

    return 0;
}

4.有待解决的一些问题

4.1.线宽的设置、背面消隐(culling)的设置

有资料说可以通过QRenderStateSet来设置,但是我设置了并没有得到有效的效果

    Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow();
    view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x2b2b2b)));

    if(0)
    {
        using namespace Qt3DRender;

        qDebug() << "frameGraph:" << view->defaultFrameGraph() << view->activeFrameGraph();

        Qt3DRender::QRenderSurfaceSelector *surSel;
        auto childNodeList = view->activeFrameGraph()->childNodes();
        foreach (Qt3DCore::QNode * childNode, childNodeList) {
            qDebug() << "child:" << childNode;
            if(qobject_cast<Qt3DRender::QRenderSurfaceSelector*>(childNode))
            {
                surSel = qobject_cast<Qt3DRender::QRenderSurfaceSelector*>(childNode);
            }
        }
        qDebug() << surSel->childNodes() << surSel->childNodes()[0]->childNodes()
                 << surSel->childNodes()[0]->childNodes()[0]->childNodes();

        qDebug() << surSel->childNodes()[0]->childNodes()[0]->childNodes()[0];

        ((Qt3DRender::QClearBuffers*)(surSel->childNodes()[0]->childNodes()[0]->childNodes()[0]))
            ->setBuffers(QClearBuffers::ColorDepthBuffer);

        QRenderStateSet *renderStateSet = new QRenderStateSet(surSel->childNodes()[0]->childNodes()[0]);
        QCullFace *cullFace = new QCullFace();
        cullFace->setMode(QCullFace::NoCulling);
        // renderStateSet->addRenderState(cullFace);

        QLineWidth *lineWidth = new QLineWidth();
        lineWidth->setValue(100);
        // renderStateSet->addRenderState(lineWidth);

        QPointSize *ptSize = new QPointSize();
        ptSize->setValue(100);
        // renderStateSet->addRenderState(ptSize);

        qDebug() << surSel->childNodes()[0]->childNodes()[0]->childNodes();
    }

4.2.法线的问题

目前好像是支持点法线,不支持面法线,假如使用index模式来渲染面片时,会渲染出奇怪的效果
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值