Qt 3D教程(三)实现对模型材质參数的控制

Qt 3D教程(三)实现对模型材质參数的控制

蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/47131841。欢迎同行前来探讨。

       上一篇教程介绍的是显示一个三维模型的基本步骤,接下来我们须要实现的是加入材质,而且希望我们通过button来控制材质的參数。

这种效果看起来非常像一个3D模型材质编辑器的样子。

那我们来尝试一下吧。

       首先我们对Settings这个类进行改动,给它增添一些属性,比方说环境光、漫反射、镜面反射以及反射系数。

通过Q_PROPERTY宏以及一系列的setter和getter函数,我们就能够做到这一点。

class Settings: public QObject
{
    Q_OBJECT
    Q_PROPERTY( bool showModel READ showModel WRITE setShowModel NOTIFY showModelChanged )
    Q_PROPERTY( QColor ambient READ ambient WRITE setAmbient NOTIFY ambientChanged )
    Q_PROPERTY( QColor diffuse READ diffuse WRITE setDiffuse NOTIFY diffuseChanged )
    Q_PROPERTY( QColor specular READ specular WRITE setSpecular NOTIFY specularChanged )
    Q_PROPERTY( float shininess READ shininess WRITE setShininess NOTIFY shininessChanged )
public:
    explicit Settings( QObject* parent = Q_NULLPTR );

    bool showModel( void ) { return m_showModel; }
    void setShowModel( bool showModel );

    QColor ambient( void ) { return m_ambient; }
    void setAmbient( const QColor& ambient );

    QColor diffuse( void ) { return m_diffuse; }
    void setDiffuse( const QColor& diffuse );

    QColor specular( void ) { return m_specular; }
    void setSpecular( const QColor& specular );

    float shininess( void ) { return m_shininess; }
    void setShininess( float shininess );
signals:
    void showModelChanged( void );
    void ambientChanged( void );
    void diffuseChanged( void );
    void specularChanged( void );
    void shininessChanged( void );
protected:
    bool            m_showModel;
    QColor          m_ambient, m_diffuse, m_specular;
    float           m_shininess;
};

以下是Settings一些函数的实现:

Settings::Settings( QObject* parent ): QObject( parent )
{
    m_showModel = true;
    m_ambient = QColor( 153, 51, 26 );
    m_diffuse = QColor( 51, 153, 26 );
    m_specular = QColor( 153, 230, 26 );
    m_shininess = 0.6;
}

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

void Settings::setAmbient( const QColor& ambient )
{
    if ( m_ambient == ambient ) return;
    m_ambient = ambient;
    emit ambientChanged( );
}

void Settings::setDiffuse( const QColor& diffuse )
{
    if ( m_diffuse == diffuse ) return;
    m_diffuse = diffuse;
    emit diffuseChanged( );
}

void Settings::setSpecular( const QColor& specular )
{
    if ( m_specular == specular ) return;
    m_specular = specular;
    emit specularChanged( );
}

void Settings::setShininess( float shininess )
{
    if ( m_shininess == shininess ) return;
    m_shininess = shininess;
    emit shininessChanged( );
}

       随后我们声明槽函数,点击环境光、漫反射和镜面反射的时候。它都会设置button的背景色,然后设置m_settings的相关成员。

 

void MainWindow::decorateButton( QPushButton* button, const QColor& color )
{
    QString styleSheetTemplate( "background: rgb( %1, %2, %3 )" );
    QString styleSheet = styleSheetTemplate.
                         arg( color.red( ) ).arg( color.green( ) ).
                         arg( color.blue( ) );
    button->setStyleSheet( styleSheet );
}

void MainWindow::on_ambientButton_clicked()
{
    QPushButton* button = qobject_cast<QPushButton*>( sender( ) );
    QColor color, prevColor;
    prevColor = m_settings.ambient( );
    color = QColorDialog::getColor( prevColor, this, "请选择一个颜色" );
    decorateButton( button, color );
    m_settings.setAmbient( color );
}

void MainWindow::on_diffuseButton_clicked()
{
    QPushButton* button = qobject_cast<QPushButton*>( sender( ) );
    QColor color, prevColor;
    prevColor = m_settings.diffuse( );
    color = QColorDialog::getColor( prevColor, this, "请选择一个颜色" );
    decorateButton( button, color );
    m_settings.setDiffuse( color );
}

void MainWindow::on_specularButton_clicked()
{
    QPushButton* button = qobject_cast<QPushButton*>( sender( ) );
    QColor color, prevColor;
    prevColor = m_settings.specular( );
    color = QColorDialog::getColor( prevColor, this, "请选择一个颜色" );
    decorateButton( button, color );
    m_settings.setSpecular( color );
}

void MainWindow::on_shininessEdit_returnPressed( void )
{
    m_settings.setShininess( ui->shininessEdit->text( ).toFloat( ) );
}

 
  

最后我们在QML中加入PhongMaterial这个类,这个类在C++中是Qt3D::Render::QPhongMaterial,它提供了基于Phong光照模型的这种材质,提供了一种很真实的显示效果。我们使用_settings这个上下文属性将上述的材质属性绑定到PhongMaterial中。加入了PhongMaterial的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
        }

        // 新加入的内容
        PhongMaterial
        {
            id: phongMaterial
            ambient: _settings.ambient
            diffuse: _settings.diffuse
            specular: _settings.specular
            shininess: _settings.shininess
        }

        components: [ chestMesh, phongMaterial ]
    }

    Configuration
    {
        controlledCamera: camera
    }
}

 
  

         程序执行截图例如以下:

       本次教程的代码均在我的github中,感兴趣的同行们能够通过git clone或者是直接下载我的git项目来获取到本套教程的全部源码。

 

This directory contains the Qt3D project for Qt5: * Qt3D QML bindings and * Qt3D C++ APIs Building Qt3D ================== Qt5 is a rapidly changing bleeding edge environment. This branch is our initial support for it and thus is also rapidly changing and bleeding edge. This branch is experimental, and unsupported. This information is provided for advanced use only. No guarantees about API stability or even if this works at all are supplied, use at your own risk. First fetch the Qt5 source tree and Qt3D master branch: cd ~/depot git clone ssh://codereview.qt-project.org:29418/qt/qt5.git cd qt5 ./init-repository --codereview-username \ --module-subset=qtbase,qtsvg,qtdeclarative,qttools,qtxmlpatterns,qtdoc,qlalr,qtrepotools,qtqa,qtlocation,qt3d git submodule foreach "git fetch gerrit && git reset --hard gerrit/master" cd qt3d scp -p -P 29418 codereview.qt-project.org:hooks/commit-msg .git/hooks/ git fetch gerrit git checkout --track -b master gerrit/master If you are reading this file then somehow you probably already got this far anyway. Now build Qt5, which will also build Qt3D as a module: cd ~/build mkdir qt5 cd qt5 ~/depot/qt5/configure -developer-build -opensource -confirm-license -no-webkit -no-phonon -nomake tests \ -nomake examples -declarative -opengl -svg && make -j 4 What's in Qt3D ================== Directory structure: src/threed/ This is the main library of the Qt3D project, containing abstractions for cross-platform GL, shaders, lighting models, and so on. src/plugins/ Scene format loading plugins. src/imports/ QML import plugins. util/ Various utilities that are useful when working with Qt3D. examples/ Some examples of using Qt3D QML bindings and Qt3D C++ API. demos/ Some more complex demos of using Qt3D QML bindings and Qt3D C++ API. tests/auto/qml3d/ Unit tests for the QML bindings. tests/auto/threed/ Unit tests for the C++ API doc/ Documentation. devices/symbian/ Symbian deployment file Documentation ============= The documentation can be generated with "make docs". It will be placed into "doc/html" in the build directory. Packages ======== This section is only for those developing Qt3D. Read on to discover how the building of packages works. This section is also important if you want to change how the structure of the Qt3D pro files work. To build Qt3D, run: qmake && make The .pro files will cause the toolchain to place the libraries, QML files and meshes of Qt3D directly into place, as part of the compile process. The files go into the bin/ directory, and the executables can be run directly from there. If you are doing a developer build, plugins will be installed in such a way that Qt will find them. After building the tree the install step is invoked using the INSTALL_ROOT environment export to cause the installation rules to place all the files into a sandboxed install tree, ready for packaging: INSTALL_ROOT=tmp make install Examples ======== Some examples require assimp library to parse the content. Go to http://assimp.sourceforge.net/ and build and install the assimp library. Then configure Qt3D to include assimp and run qmake && make.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值