zoukankan      html  css  js  c++  java
  • 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项目来获取到本套教程的全部源码。

  • 相关阅读:
    java synchronized
    Java多线程的常见例子
    List,ArrayList
    BufferedInputStream与BufferedOutputStream
    super,this
    ServletConfig与ServletContext
    [转] 编写高效的 CSS 选择器
    浏览器是怎样工作的:渲染引擎,HTML解析
    sublime插件insertDate显示ISO时间
    《十日谈》摘要1
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7079488.html
Copyright © 2011-2022 走看看