QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
qgsphongtexturedmaterialsettings.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsphongtexturedmaterialsettings.cpp
3  --------------------------------------
4  Date : August 2020
5  Copyright : (C) 2020 by Nyall Dawson
6  Email : nyall dot dawson at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
17 
18 #include "qgssymbollayerutils.h"
19 #include "qgsapplication.h"
20 #include "qgsimagecache.h"
21 #include "qgsimagetexture.h"
22 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
23 #include <Qt3DExtras/QDiffuseMapMaterial>
24 #else
25 #include <Qt3DExtras/QDiffuseSpecularMaterial>
26 #endif
27 #include <Qt3DExtras/QPhongMaterial>
28 #include <Qt3DRender/QPaintedTextureImage>
29 #include <Qt3DRender/QTexture>
30 #include <Qt3DRender/QParameter>
31 #include <Qt3DRender/QEffect>
32 #include <QMap>
33 
34 
36 {
37  return QStringLiteral( "phongtextured" );
38 }
39 
41 {
42  switch ( technique )
43  {
45  case QgsMaterialSettingsRenderingTechnique::TrianglesDataDefined: //technique is supported but color can't be datadefined
46  return true;
47 
53  return false;
54  }
55  return false;
56 }
57 
59 {
61 }
62 
64 {
65  return new QgsPhongTexturedMaterialSettings( *this );
66 }
67 
69 {
70  return mTextureRotation;
71 }
72 
73 void QgsPhongTexturedMaterialSettings::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
74 {
75  mAmbient = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "ambient" ), QStringLiteral( "25,25,25" ) ) );
76  mSpecular = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "specular" ), QStringLiteral( "255,255,255" ) ) );
77  mShininess = elem.attribute( QStringLiteral( "shininess" ) ).toFloat();
78  mDiffuseTexturePath = elem.attribute( QStringLiteral( "diffuse_texture_path" ), QString() );
79  mTextureScale = elem.attribute( QStringLiteral( "texture_scale" ), QString( "1.0" ) ).toFloat();
80  mTextureRotation = elem.attribute( QStringLiteral( "texture-rotation" ), QString( "0.0" ) ).toFloat();
81 
82  QgsAbstractMaterialSettings::readXml( elem, context );
83 }
84 
85 void QgsPhongTexturedMaterialSettings::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
86 {
87  elem.setAttribute( QStringLiteral( "ambient" ), QgsSymbolLayerUtils::encodeColor( mAmbient ) );
88  elem.setAttribute( QStringLiteral( "specular" ), QgsSymbolLayerUtils::encodeColor( mSpecular ) );
89  elem.setAttribute( QStringLiteral( "shininess" ), mShininess );
90  elem.setAttribute( QStringLiteral( "diffuse_texture_path" ), mDiffuseTexturePath );
91  elem.setAttribute( QStringLiteral( "texture_scale" ), mTextureScale );
92  elem.setAttribute( QStringLiteral( "texture-rotation" ), mTextureRotation );
93 
95 }
96 
99 {
100  switch ( technique )
101  {
108  {
109  bool fitsInCache = false;
110  QImage textureSourceImage = QgsApplication::imageCache()->pathAsImage( mDiffuseTexturePath, QSize(), true, 1.0, fitsInCache );
111  ( void )fitsInCache;
112 
113  if ( !textureSourceImage.isNull() )
114  {
115  QgsImageTexture *textureImage = new QgsImageTexture( textureSourceImage );
116 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
117  Qt3DExtras::QDiffuseMapMaterial *material = new Qt3DExtras::QDiffuseMapMaterial;
118  material->diffuse()->addTextureImage( textureImage );
119 
120  material->diffuse()->wrapMode()->setX( Qt3DRender::QTextureWrapMode::Repeat );
121  material->diffuse()->wrapMode()->setY( Qt3DRender::QTextureWrapMode::Repeat );
122  material->diffuse()->wrapMode()->setZ( Qt3DRender::QTextureWrapMode::Repeat );
123 #else
124  Qt3DExtras::QDiffuseSpecularMaterial *material = new Qt3DExtras::QDiffuseSpecularMaterial;
125 
126  Qt3DRender::QTexture2D *texture = new Qt3DRender::QTexture2D();
127  texture->addTextureImage( textureImage );
128 
129  texture->wrapMode()->setX( Qt3DRender::QTextureWrapMode::Repeat );
130  texture->wrapMode()->setY( Qt3DRender::QTextureWrapMode::Repeat );
131  texture->wrapMode()->setZ( Qt3DRender::QTextureWrapMode::Repeat );
132 
133  texture->setSamples( 4 );
134 
135  texture->setGenerateMipMaps( true );
136  texture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
137  texture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
138 
139  material->setDiffuse( QVariant::fromValue( texture ) );
140 #endif
141 
142  material->setSpecular( mSpecular );
143  material->setAmbient( mAmbient );
144  material->setShininess( mShininess );
145  material->setTextureScale( mTextureScale );
146 
147  if ( context.isSelected() )
148  {
149  // update the material with selection colors
150  // TODO : dampen the color of diffuse texture
151  // mat->setDiffuse( context.map().selectionColor() );
152  material->setAmbient( context.selectionColor().darker() );
153  }
154 
155  return material;
156  }
157  else
158  {
159  Qt3DExtras::QPhongMaterial *material = new Qt3DExtras::QPhongMaterial;
160  material->setAmbient( mAmbient );
161  material->setSpecular( mSpecular );
162  material->setShininess( mShininess );
163 
164  if ( context.isSelected() )
165  {
166  // update the material with selection colors
167  material->setDiffuse( context.selectionColor() );
168  material->setAmbient( context.selectionColor().darker() );
169  }
170  return material;
171  }
172  }
173 
175  return nullptr;
176 
177  }
178  return nullptr;
179 }
180 
182 {
183  QMap<QString, QString> parameters;
184  parameters[ QStringLiteral( "Ka" ) ] = QStringLiteral( "%1 %2 %3" ).arg( mAmbient.redF() ).arg( mAmbient.greenF() ).arg( mAmbient.blueF() );
185  parameters[ QStringLiteral( "Ks" ) ] = QStringLiteral( "%1 %2 %3" ).arg( mSpecular.redF() ).arg( mSpecular.greenF() ).arg( mSpecular.blueF() );
186  parameters[ QStringLiteral( "Ns" ) ] = QString::number( mShininess );
187  return parameters;
188 }
189 
190 void QgsPhongTexturedMaterialSettings::addParametersToEffect( Qt3DRender::QEffect *effect ) const
191 {
192  Qt3DRender::QParameter *ambientParameter = new Qt3DRender::QParameter( QStringLiteral( "ka" ), QColor::fromRgbF( 0.05f, 0.05f, 0.05f, 1.0f ) );
193  Qt3DRender::QParameter *specularParameter = new Qt3DRender::QParameter( QStringLiteral( "ks" ), QColor::fromRgbF( 0.01f, 0.01f, 0.01f, 1.0f ) );
194  Qt3DRender::QParameter *shininessParameter = new Qt3DRender::QParameter( QStringLiteral( "shininess" ), 150.0f );
195 
196  ambientParameter->setValue( mAmbient );
197  specularParameter->setValue( mSpecular );
198  shininessParameter->setValue( mShininess );
199 
200  effect->addParameter( ambientParameter );
201  effect->addParameter( specularParameter );
202  effect->addParameter( shininessParameter );
203 }
virtual void writeXml(QDomElement &element, const QgsReadWriteContext &) const
Writes settings to a DOM element.
virtual void readXml(const QDomElement &element, const QgsReadWriteContext &)
Reads settings from a DOM element.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
Holds an image that can be used as a texture in the 3D view.
QColor selectionColor() const
Returns the color for representing materials in a selected state.
bool isSelected() const
Returns true if the material should represent a selected state.
QgsPhongTexturedMaterialSettings()=default
Constructor for QgsPhongTexturedMaterialSettings.
void addParametersToEffect(Qt3DRender::QEffect *effect) const override
Adds parameters from the material to a destination effect.
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const override
Writes settings to a DOM element.
float textureRotation() const
Returns the texture rotation, in degrees.
QString type() const override
Returns the unique type name for the material.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context) override
Reads settings from a DOM element.
static bool supportsTechnique(QgsMaterialSettingsRenderingTechnique technique)
Returns true if the specified technique is supported by the Phong material.
QgsPhongTexturedMaterialSettings * clone() const override
Clones the material settings.
static QgsAbstractMaterialSettings * create()
Returns a new instance of QgsPhongTexturedMaterialSettings.
QMap< QString, QString > toExportParameters() const override
Returns the parameters to be exported to .mtl file.
Qt3DRender::QMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const override
Creates a new QMaterial object representing the material settings.
The class is used as a container of context for various read/write operations on other objects.
static QColor decodeColor(const QString &str)
static QString encodeColor(const QColor &color)
QgsMaterialSettingsRenderingTechnique
Material rendering techniques 3.
@ Points
Point based rendering, requires point data.
@ Triangles
Triangle based rendering (default)
@ TrianglesFromModel
Triangle based rendering, using a model object source.
@ Lines
Line based rendering, requires line data.
@ TrianglesDataDefined
Triangle based rendering with possibility of datadefined color.
@ InstancedPoints
Instanced based rendering, requiring triangles and point data.
@ TrianglesWithFixedTexture
Triangle based rendering, using a fixed, non-user-configurable texture (e.g. for terrain rendering)