C++ 未渲染Qt3D SceneLoader实体

C++ 未渲染Qt3D SceneLoader实体,c++,qt3d,qt5.11,C++,Qt3d,Qt5.11,我正在尝试创建一个Qt3D原型,它能够渲染包含透明对象的obj。因此,我需要以某种方式将QSortPolicy与自定义框架图结合起来。我在互联网上找到了几个例子(不幸的是,没有太多的QT3D C++例子)。原型的来源如下所示。问题是我向根实体添加了一个QTorusMesh和QSceneLoader的内容,但是当渲染时只显示圆环体,obj(在本例中是猴子)不会渲染,我不知道为什么,也不知道如何调试它。我转储了所有的树(场景图和帧图),没有发现任何不一致。我能想到的唯一一件事是,加载的对象不知何故需

我正在尝试创建一个Qt3D原型,它能够渲染包含透明对象的obj。因此,我需要以某种方式将
QSortPolicy
与自定义框架图结合起来。我在互联网上找到了几个例子(不幸的是,没有太多的QT3D C++例子)。原型的来源如下所示。问题是我向根实体添加了一个
QTorusMesh
QSceneLoader
的内容,但是当渲染时只显示圆环体,obj(在本例中是猴子)不会渲染,我不知道为什么,也不知道如何调试它。我转储了所有的树(场景图和帧图),没有发现任何不一致。我能想到的唯一一件事是,加载的对象不知何故需要一个不同的渲染器(
qgeometryrender
),它需要添加到帧图中?有人知道我做错了什么吗

例如:

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
类场景漫游者:公共QObject
{
公众:
场景漫游器(Qt3DRender::QSceneLoader*加载程序):
装载机(装载机)
{}
void onStatusChanged();
私人:
void walkEntity(Qt3DCore::QEntity*e,int-depth=0);
Qt3DRender::QSceneLoader*m_loader;
};
void SceneWalker::onStatusChanged()
{
qDebug()状态()!=Qt3DRender::QSceneLoader::Ready)
返回;
//QSceneLoader实例是实体的组件。加载的场景
//树被添加到此实体下。
QVector entities=m_loader->entities();
//从技术上讲,可能有多个实体引用场景加载程序
//但不鼓励分享,在我们的情况下,无论如何都会有一个。
if(entities.isEmpty())
返回;
Qt3DCore::QEntity*root=实体[0];
//打印树。
实体(根);
//要访问给定节点(如场景中的命名网格),请使用QObject::findChild()。
//场景结构和名称始终取决于资源。
Qt3DCore::QEntity*e=root->findChild(QStringLiteral(“平面推进器网格”);//toyplane.obj
如果(e)
qDebug()设置透视投影(45.f、16.0f/9.0f、0.01f、1000.f);
objectsCamera->setPosition(QVector3D(0,0,-10));
objectsCamera->setViewCenter(QVector3D(0,0,0));
objectsCamera->setUpVector(QVector3D(0,1,0));
objectsCameraSelector->setCamera(objectsCamera);
//设置新的框架图
窗口->设置活动框架图(renderSurfaceSelector);
window->renderSettings()->setRenderPolicy(Qt3DRender::QRenderSettings::Always);
//摄像机控制
qt3detras::QOrbitCameraController*camController=新的qt3detras::QOrbitCameraController(rootEntity);
凸轮控制器->设定线速度(50.0f);
camController->setLookSpeed(180.0f);
camController->setCamera(objectsCamera);
//环面
Qt3DCore::QEntity*torusEntity=新的Qt3DCore::QEntity(rootEntity);
Qt3DExtras::QTorusMesh*torusMesh=新的Qt3DExtras::QTorusMesh(torusEntity);
圆环网格->固定片(50.0f);
圆环网格->设置环(50.0f);
圆环网格->设定半径(2.0f);
Qt3DExtras::QPhongMaterial*torusMaterial=新的Qt3DExtras::QPhongMaterial(torusEntity);
圆环体材料->设置环境温度(Qt::灰色);
Qt3DCore::QTransform*torusTransform=新的Qt3DCore::QTransform(torusEntity);
torusTransform->setTranslation(QVector3D(0.0f,0.0f,10.0f));
torusTransform->setRotationY(50.0f);
torusTransform->setScale(2.0f);
torusEntity->addComponent(torusTransform);
torusEntity->addComponent(torusMesh);
torusEntity->添加组件(torusMaterial);
torusEntity->addComponent(objectsLayer);
//场景加载器
Qt3DCore::QEntity*sceneLoaderEntity=新的Qt3DCore::QEntity(rootEntity);
Qt3DRender::QSceneLoader*sceneLoader=新的Qt3DRender::QSceneLoader(sceneloaderrentity);
sceneLoader->setSource(QUrl::fromLocalFile(“monkey.obj”);
//转化
Qt3DCore::QTTransform*sceneLoaderTransform=新的Qt3DCore::QTTransform(sceneLoaderEntity);
sceneLoaderTransform->setScale(2.0f);
sceneLoaderTransform->setTranslation(QVector3D(0.0f,0.0f,10.0f));
场景漫游者场景漫游者(场景漫游者);
QObject::connect(sceneLoader,&Qt3DRender::QSceneLoader::statusChanged,&sceneWalker,&sceneWalker::onStatusChanged);
sceneLoaderEntity->addComponent(sceneLoader);
sceneLoaderEntity->addComponent(sceneLoaderTransform);
sceneLoaderEntity->addComponent(objectsLayer);
窗口->显示();
返回app.exec();
}

问题在于,您实际上并没有将猴子添加到对象层
QSceneLoader
创建自己的场景子树,即使OBJ文件包含单个对象。因此,您只需将子树的根实体添加到对象层

SceneWalker
对象遍历
QSceneLoader
子树并提供有关其结构的信息。您只需查看控制台输出,找到要渲染的实体的名称,然后将它们附加到所需的层

这必须使用信号和插槽异步完成。创建
QSceneLoader
对象后立即执行此操作(假设网格名为“monkey”):

由于您使用的是OBJ文件,您甚至可以完全抛弃
SceneWalker
。OBJ文件是基于文本的,因此只需使用文本编辑器打开网格即可找到网格的名称

如果成功使用层过滤器,则无需使用
QSortPolicy
(签出)

#include <QGuiApplication>

#include <Qt3DCore/QEntity>
#include <Qt3DCore/QTransform>
#include <Qt3DCore/QAspectEngine>

#include <Qt3DInput/QInputAspect>

#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DExtras/QOrbitCameraController>
#include <Qt3DExtras/QTorusMesh>

#include <Qt3DRender/QCamera>
#include <Qt3DRender/QRenderAspect>
#include <Qt3DRender/QSceneLoader>
#include <Qt3DRender/QRenderSurfaceSelector>
#include <Qt3DRender/QClearBuffers>
#include <Qt3DRender/QLayerFilter>
#include <Qt3DRender/QViewport>
#include <Qt3DRender/QCameraSelector>
#include <Qt3DRender/QLayer>
#include <Qt3DRender/QRenderSettings>

class SceneWalker : public QObject
{
public:
    SceneWalker(Qt3DRender::QSceneLoader* loader):
        m_loader(loader)
    {}

    void onStatusChanged();

private:
    void walkEntity(Qt3DCore::QEntity* e, int depth = 0);

    Qt3DRender::QSceneLoader* m_loader;
};

void SceneWalker::onStatusChanged()
{
    qDebug() << "Status changed:" << m_loader->status();
    if (m_loader->status() != Qt3DRender::QSceneLoader::Ready)
        return;

    // The QSceneLoader instance is a component of an entity. The loaded scene
    // tree is added under this entity.
    QVector<Qt3DCore::QEntity*> entities = m_loader->entities();

    // Technically there could be multiple entities referencing the scene loader
    // but sharing is discouraged, and in our case there will be one anyhow.
    if (entities.isEmpty())
        return;

    Qt3DCore::QEntity* root = entities[0];
    // Print the tree.
    walkEntity(root);

    // To access a given node (like a named mesh in the scene), use QObject::findChild().
    // The scene structure and names always depend on the asset.
    Qt3DCore::QEntity* e = root->findChild<Qt3DCore::QEntity*>(QStringLiteral("PlanePropeller_mesh")); // toyplane.obj
    if (e)
        qDebug() << "Found propeller node" << e << "with components" << e->components();
}

void SceneWalker::walkEntity(Qt3DCore::QEntity* e, int depth)
{
    Qt3DCore::QNodeVector nodes = e->childNodes();
    for (int i = 0; i < nodes.count(); ++i)
    {
        Qt3DCore::QNode* node = nodes[i];
        Qt3DCore::QEntity* entity = qobject_cast<Qt3DCore::QEntity*>(node);
        if (entity)
        {
            QString indent;
            indent.fill(' ', depth * 2);
            qDebug().noquote() << indent << "Entity:" << entity << "Components:" << entity->components();
            walkEntity(entity, depth + 1);
        }
    }
}

int main(int argc, char* argv[])
{
    QGuiApplication app(argc, argv);

    Qt3DExtras::Qt3DWindow* window = new Qt3DExtras::Qt3DWindow();

    // Root
    Qt3DCore::QEntity* rootEntity = new Qt3DCore::QEntity();
    window->setRootEntity(rootEntity);

    Qt3DRender::QRenderSurfaceSelector *renderSurfaceSelector = new Qt3DRender::QRenderSurfaceSelector();
    renderSurfaceSelector->setSurface(window);

    // clearing the buffers
    Qt3DRender::QClearBuffers* clearBuffers = new Qt3DRender::QClearBuffers(renderSurfaceSelector);
    clearBuffers->setBuffers(Qt3DRender::QClearBuffers::ColorDepthBuffer);

    // Framegraph for objects
    Qt3DRender::QLayerFilter* objectsLayerFilter = new Qt3DRender::QLayerFilter(renderSurfaceSelector);
    Qt3DRender::QLayer* objectsLayer = new Qt3DRender::QLayer(objectsLayerFilter);
    objectsLayerFilter->addLayer(objectsLayer);
    Qt3DRender::QViewport* viewport = new Qt3DRender::QViewport(objectsLayer);
    Qt3DRender::QCameraSelector* objectsCameraSelector = new Qt3DRender::QCameraSelector(viewport);
    Qt3DRender::QCamera* objectsCamera = new Qt3DRender::QCamera(objectsCameraSelector);
    objectsCamera->lens()->setPerspectiveProjection(45.f, 16.0f/9.0f, 0.01f, 1000.f);
    objectsCamera->setPosition(QVector3D(0, 0, -10));
    objectsCamera->setViewCenter(QVector3D(0, 0, 0));
    objectsCamera->setUpVector(QVector3D(0, 1, 0));
    objectsCameraSelector->setCamera(objectsCamera);

    // Set the new framegraph
    window->setActiveFrameGraph(renderSurfaceSelector);
    window->renderSettings()->setRenderPolicy(Qt3DRender::QRenderSettings::Always);

    // camera controls
    Qt3DExtras::QOrbitCameraController* camController = new Qt3DExtras::QOrbitCameraController(rootEntity);
    camController->setLinearSpeed(50.0f);
    camController->setLookSpeed(180.0f);
    camController->setCamera(objectsCamera);

    // Torus
    Qt3DCore::QEntity* torusEntity = new Qt3DCore::QEntity(rootEntity);
    Qt3DExtras::QTorusMesh* torusMesh = new Qt3DExtras::QTorusMesh(torusEntity);
    torusMesh->setSlices(50.0f);
    torusMesh->setRings(50.0f);
    torusMesh->setRadius(2.0f);
    Qt3DExtras::QPhongMaterial* torusMaterial = new Qt3DExtras::QPhongMaterial(torusEntity);
    torusMaterial->setAmbient(Qt::gray);
    Qt3DCore::QTransform* torusTransform = new Qt3DCore::QTransform(torusEntity);
    torusTransform->setTranslation(QVector3D(0.0f, 0.0f, 10.0f));
    torusTransform->setRotationY(50.0f);
    torusTransform->setScale(2.0f);
    torusEntity->addComponent(torusTransform);
    torusEntity->addComponent(torusMesh);
    torusEntity->addComponent(torusMaterial);
    torusEntity->addComponent(objectsLayer);

    // Scene loader
    Qt3DCore::QEntity* sceneLoaderEntity = new Qt3DCore::QEntity(rootEntity);
    Qt3DRender::QSceneLoader* sceneLoader = new Qt3DRender::QSceneLoader(sceneLoaderEntity);
    sceneLoader->setSource(QUrl::fromLocalFile("monkey.obj"));

    // Transform
    Qt3DCore::QTransform* sceneLoaderTransform = new Qt3DCore::QTransform(sceneLoaderEntity);
    sceneLoaderTransform->setScale(2.0f);
    sceneLoaderTransform->setTranslation(QVector3D(0.0f, 0.0f, 10.0f));

    SceneWalker sceneWalker(sceneLoader);
    QObject::connect(sceneLoader, &Qt3DRender::QSceneLoader::statusChanged, &sceneWalker, &SceneWalker::onStatusChanged);

    sceneLoaderEntity->addComponent(sceneLoader);
    sceneLoaderEntity->addComponent(sceneLoaderTransform);
    sceneLoaderEntity->addComponent(objectsLayer);

    window->show();

    return app.exec();
}
    QObject::connect(sceneLoader, &Qt3DRender::QSceneLoader::statusChanged, &app,
        [sceneLoader, objectsLayer](Qt3DRender::QSceneLoader::Status s) {
            if (s == Qt3DRender::QSceneLoader::Status::Ready)
                sceneLoader->entity("monkey")->addComponent(objectsLayer);
    });