1. 程式人生 > >Qt 3D教程(二)初步顯示3D的內容

Qt 3D教程(二)初步顯示3D的內容

初始 應用 frame 通過 net settings mod rgba bsp

Qt3D教程(二)初步顯示3D的內容

前一篇很easy,全然就沒有牽涉到3D的內容,它僅僅是我們搭建3D應用的基本框架而已,而這一篇。我們將要利用它來初步地顯示3D的內容了!

本次目的是將程序中間的內容替換成3D的視圖,而這一切也只是十幾行代碼。要不我們來試一試吧!

蔣彩陽原創文章,首發地址:http://blog.csdn.net/gamesdev/article/details/47131099。歡迎同行前來探討。

首先我們須要對我們的MainWindow.cpp文件進行改動,在此基礎上加入一些內容:

#include <QQmlAspectEngine>
#include <QRenderAspect>
#include <QInputAspect>
#include <QQmlContext>
#include <QWindow>

#include "MainWindow.h"
#include "ui_MainWindow.h"

class View3D: public QWindow
{
public:
    View3D( QScreen* targetScreen = Q_NULLPTR ): QWindow( targetScreen )
    {
        setSurfaceType( QSurface::OpenGLSurface );

        QSurfaceFormat format;
        format.setSamples( 4 );
        setFormat( format );

        create( );
    }
};


Settings::Settings( QObject* parent ): QObject( parent )
{
    m_showModel = true;
}

void Settings::setShowModel( bool showModel )
{
    if ( m_showModel == showModel ) return;
    m_showModel = showModel;
    emit showModelChanged( );
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    using namespace Qt3D;
    using namespace Qt3D::Quick;
    // 創建一個3D的視圖
    // 1
    View3D* view3D = new View3D;

    // 2
    QQmlAspectEngine* engine = new QQmlAspectEngine( this );
    engine->aspectEngine( )->registerAspect( new QRenderAspect );
    engine->aspectEngine( )->registerAspect( new QInputAspect );

    // 3
    QVariantMap data;
    data.insert( QStringLiteral( "surface" ),
                 QVariant::fromValue( static_cast<QSurface*>( view3D ) ) );
    data.insert( QStringLiteral( "eventSource" ),
                 QVariant::fromValue( view3D ) );
    engine->aspectEngine( )->setData( data );

    // 4
    engine->qmlEngine( )->rootContext( )->setContextProperty( "_settings", &m_settings );

    // 5
    engine->aspectEngine( )->initialize( );
    engine->setSource( QUrl( "qrc:/qml/main.qml" ) );

    QVBoxLayout* l = qobject_cast<QVBoxLayout*>( ui->centralwidget->layout( ) );
    l->insertWidget( 0, QWidget::createWindowContainer( view3D ) );
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_showModelButton_clicked()
{
    bool show = m_settings.showModel( );
    show = !show;
    ui->showModelButton->setText( show? "隱藏模型": "顯示模型" );
    m_settings.setShowModel( show );
}

這裏我們使用了QWindow來替代我們以前使用的QWidget,而且使用了QWidget:: createWindowContainer()函數來將QWindow的內容嵌入QWidget框架中;緊接著我們在構造函數中創建了QQmlAspectEngine類實例,而且註冊了QRenderAspect和QInputAspect。隨後我們使用一個QVariantMap數據結構,將surface以及eventSource以鍵值對的形式存儲起來供QAspectEngine使用。接著作為可選的內容,我們為了讓C++這一部分控制QML。我們定義了一個Settings類,而且將m_settings註入QML環境作為上下文變量;最後我們使用initialize()函數初始化QAspectEngine,而且指定了我們須要展示的場景數據:main.qml。

此外。當button按下的時候,我們能夠通過改變m_settings的屬性從而控制我們是否想要顯示模型。

同一時候我們還必須在main.qml中作一些設置:

import Qt3D 2.0
import Qt3D.Renderer 2.0

Entity
{
    id: root

    Camera
    {
        id: camera
        position: Qt.vector3d( 0.0, 20.0, 100.0 )
        projectionType: CameraLens.PerspectiveProjection
        fieldOfView: 45
        aspectRatio: 16.0 / 9.0
        nearPlane : 0.1
        farPlane : 1000.0
        upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
        viewCenter: Qt.vector3d( 0.0, 20.0, 0.0 )
    }

    components: FrameGraph
    {
        ForwardRenderer
        {
            clearColor: Qt.rgba( 0.2, 0, 0, 1 )
            camera: camera
        }
    }

    Entity
    {
        Mesh
        {
            id: chestMesh
            source: "qrc:/assets/Chest.obj"
            enabled: _settings.showModel
        }

        components: [ chestMesh ]
    }

    Configuration
    {
        controlledCamera: camera
    }
}

如上面所看到的,我們在名為root的Entity中定義了一個攝像機、一個實體。另一些必要的設置。

同一時候我們通過綁定_settings.showModel來控制Mesh的顯示或者隱藏。

技術分享

本次教程的代碼均在我的github中,感興趣的同行們能夠通過git clone或者是直接下載我的git項目來獲取到本套教程的全部源碼。

Qt 3D教程(二)初步顯示3D的內容