首页 > 解决方案 > 自定义 QQuick3DGeometry 不显示

问题描述

尝试为 QtQuick3D 实现自定义几何图形:

mycustomgeometry.h:

#ifndef MYCUSTOMGEOMETRY_H
#define MYCUSTOMGEOMETRY_H

#include <QQuick3DGeometry>

class MyCustomGeometry : public QQuick3DGeometry
{
    Q_OBJECT
public:
    MyCustomGeometry();
    virtual ~MyCustomGeometry();

signals:

public slots:
    void setData(QByteArray vertexData, QByteArray indexData);

};

#endif // MYCUSTOMGEOMETRY_H

mycustomgeometry.cpp:

#include "mycustomgeometry.h"

#include <QVector3D>

// simulate data coming from my application (should look like a cut cuboid)
static unsigned char vertexData[] = {
    0x00, 0x00, 0xe0, 0xb3, 0x8c, 0xca, 0x4c, 0xbd, 0x1c, 0x63, 0x89, 0x3d,
    0x00, 0x00, 0x60, 0x35, 0x0c, 0xcf, 0x4c, 0x3d, 0xa4, 0x61, 0x89, 0x3d,
    0x64, 0x2e, 0x37, 0xbd, 0xb8, 0xcc, 0x4c, 0xbd, 0x00, 0x2a, 0xb7, 0xbc,
    0x68, 0x2d, 0x37, 0xbd, 0xe4, 0xcc, 0x4c, 0x3d, 0xe0, 0x2f, 0xb7, 0xbc,
    0x80, 0x2d, 0x37, 0x3d, 0xa4, 0xcb, 0x4c, 0xbd, 0x18, 0x2f, 0x37, 0x3d,
    0x80, 0x2e, 0x37, 0x3d, 0xf0, 0xcd, 0x4c, 0x3d, 0x28, 0x2c, 0x37, 0x3d,
    0xd8, 0x2c, 0x37, 0x3d, 0xf8, 0xce, 0x4c, 0xbd, 0xa0, 0x61, 0x89, 0xbd,
    0xd8, 0x2d, 0x37, 0x3d, 0xa4, 0xca, 0x4c, 0x3d, 0x20, 0x63, 0x89, 0xbd
};
static unsigned char indexData[] = {
    0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
    0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
    0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
    0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
    0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
    0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
    0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
    0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
};

MyCustomGeometry::MyCustomGeometry()
{
    QByteArray v(reinterpret_cast<char*>(::vertexData), sizeof(::vertexData));
    QByteArray i(reinterpret_cast<char*>(::indexData), sizeof(::indexData));
    setData(v, i);
}

MyCustomGeometry::~MyCustomGeometry()
{
}

void MyCustomGeometry::setData(QByteArray vertexData, QByteArray indexData)
{
    clear();
    setPrimitiveType(PrimitiveType::Triangles);
    addAttribute(Attribute::PositionSemantic, 0, Attribute::F32Type);
    addAttribute(Attribute::IndexSemantic, 0, Attribute::U32Type);
    addAttribute(Attribute::NormalSemantic, 0, Attribute::F32Type);
    setVertexData(vertexData);
    setIndexData(indexData);
    setStride(sizeof(float) * 3);

    QVector3D boundsMin, boundsMax;
    auto vertices = reinterpret_cast<const float*>(vertexData.constData());
    for(size_t i = 0; i < vertexData.length() / sizeof(float); i += 3)
    {
        for(size_t j = 0; j < 3; j++)
        {
            boundsMin[j] = (std::min(vertices[i + j], i == 0 ? vertices[i + j] : boundsMin[j]));
            boundsMax[j] = (std::max(vertices[i + j], i == 0 ? vertices[i + j] : boundsMax[j]));
        }
    }
    setBounds(boundsMin, boundsMax);
}

main.qml:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick3D 1.15
import QtQuick3D.Helpers 1.15
import QtQuick.Controls 2.15
import MyCustomGeometry 1.0

Window {
    id: mainWindow
    width: 400
    height: 300
    visible: true
    flags: Qt.Tool
    title: qsTr("3D demo")

    View3D {
        id: view
        anchors.fill: parent
        camera: camera
        renderMode: View3D.Overlay

        PerspectiveCamera {
            id: camera
            position: Qt.vector3d(0, 200, 300)
            eulerRotation.x: -30
        }

        WasdController {
            controlledObject: camera
            mouseEnabled: true
        }

        DirectionalLight {
            eulerRotation.x: -30
        }

        Model {
            id: cube
            objectName: "cube"
            visible: true
            position: Qt.vector3d(-100, 0, 0)
            scale: Qt.vector3d(slider.k, slider.k, slider.k)
            source: "#Cube"
            materials: [DefaultMaterial {diffuseColor: "red"}]
            eulerRotation.y: 90
        }

        Model {
            id: sphere
            objectName: "sphere"
            visible: true
            position: Qt.vector3d(100, 0, 0)
            scale: Qt.vector3d(slider.k, slider.k, slider.k)
            //source: "#Sphere"
            geometry: MyCustomGeometry {}
            materials: [DefaultMaterial {diffuseColor: "blue"}]
            eulerRotation.y: 90
        }
    }

    Slider {
        id: slider
        property real k: Math.pow(10, slider.value)
        from: -3; to: 6; value: 3
    }
}

立方体和球体(在评论geometry:和取消评论时source:)正确显示。

但是具有自定义几何形状的模型没有。

我也尝试使用 16 位整数作为索引,但得到了相同的结果。

编辑:在 Qt 6.0.0 上测试并且可以工作,所以这是一个仅限于 Qt 5.15.2 的问题

标签: qtqmlqtquick3d

解决方案


如果根据QTBUG-89420name设置属性,它也适用于 Qt 5 :

MyCustomGeometry::MyCustomGeometry()
{
    QByteArray v(reinterpret_cast<char*>(::vertexData), sizeof(::vertexData));
    QByteArray i(reinterpret_cast<char*>(::indexData), sizeof(::indexData));
    setData(v, i);
    setName("MyCustomGeometry");
}

推荐阅读