QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsgoochmaterialsettings.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgoochmaterialsettings.cpp
3  --------------------------------------
4  Date : July 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 "qgslinematerial_p.h"
20 #include <Qt3DExtras/QGoochMaterial>
21 #include <Qt3DRender/QAttribute>
22 #include <Qt3DRender/QBuffer>
23 #include <Qt3DRender/QGeometry>
24 #include <Qt3DRender/QParameter>
25 #include <Qt3DRender/QEffect>
26 #include <Qt3DRender/QTechnique>
27 #include <Qt3DRender/QGraphicsApiFilter>
28 #include <QUrl>
29 
31 {
32  return QStringLiteral( "gooch" );
33 }
34 
36 {
37  return new QgsGoochMaterialSettings();
38 }
39 
41 {
42  switch ( technique )
43  {
48  return true;
49 
53  return false;
54  }
55  return false;
56 }
57 
59 {
60  return new QgsGoochMaterialSettings( *this );
61 }
62 
63 void QgsGoochMaterialSettings::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
64 {
65  mWarm = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "warm" ), QStringLiteral( "107,0,107" ) ) );
66  mCool = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "cool" ), QStringLiteral( "255,130,0" ) ) );
67  mDiffuse = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "diffuse" ), QStringLiteral( "178,178,178" ) ) );
68  mSpecular = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "specular" ) ) );
69  mShininess = elem.attribute( QStringLiteral( "shininess2" ), QStringLiteral( "100" ) ).toFloat();
70  mAlpha = elem.attribute( QStringLiteral( "alpha" ), QStringLiteral( "0.25" ) ).toFloat();
71  mBeta = elem.attribute( QStringLiteral( "beta" ), QStringLiteral( "0.5" ) ).toFloat();
72 
73  QgsAbstractMaterialSettings::readXml( elem, context );
74 }
75 
76 void QgsGoochMaterialSettings::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
77 {
78  elem.setAttribute( QStringLiteral( "warm" ), QgsSymbolLayerUtils::encodeColor( mWarm ) );
79  elem.setAttribute( QStringLiteral( "cool" ), QgsSymbolLayerUtils::encodeColor( mCool ) );
80  elem.setAttribute( QStringLiteral( "diffuse" ), QgsSymbolLayerUtils::encodeColor( mDiffuse ) );
81  elem.setAttribute( QStringLiteral( "specular" ), QgsSymbolLayerUtils::encodeColor( mSpecular ) );
82  elem.setAttribute( QStringLiteral( "shininess2" ), mShininess );
83  elem.setAttribute( QStringLiteral( "alpha" ), mAlpha );
84  elem.setAttribute( QStringLiteral( "beta" ), mBeta );
85 
87 }
88 
89 QMap<QString, QString> QgsGoochMaterialSettings::toExportParameters() const
90 {
91  return QMap<QString, QString>();
92 }
93 
95 {
96  switch ( technique )
97  {
102  {
103  if ( dataDefinedProperties().hasActiveProperties() )
104  return dataDefinedMaterial();
105  Qt3DExtras::QGoochMaterial *material = new Qt3DExtras::QGoochMaterial;
106  material->setDiffuse( mDiffuse );
107  material->setWarm( mWarm );
108  material->setCool( mCool );
109 
110  material->setSpecular( mSpecular );
111  material->setShininess( mShininess );
112  material->setAlpha( mAlpha );
113  material->setBeta( mBeta );
114 
115  if ( context.isSelected() )
116  {
117  // update the material with selection colors
118  material->setDiffuse( context.selectionColor() );
119  }
120  return material;
121  }
122 
126  return nullptr;
127  }
128  return nullptr;
129 }
130 
131 void QgsGoochMaterialSettings::addParametersToEffect( Qt3DRender::QEffect * ) const
132 {
133 }
134 
136 {
137 
138  QColor diffuse = dataDefinedProperties().valueAsColor( Diffuse, expressionContext, mDiffuse );
139  QColor warm = dataDefinedProperties().valueAsColor( Warm, expressionContext, mWarm );
140  QColor cool = dataDefinedProperties().valueAsColor( Cool, expressionContext, mCool );
141  QColor specular = dataDefinedProperties().valueAsColor( Specular, expressionContext, mSpecular );
142 
143 
144  QByteArray array;
145  array.resize( sizeof( unsigned char ) * 12 );
146  unsigned char *fptr = reinterpret_cast<unsigned char *>( array.data() );
147 
148  *fptr++ = static_cast<unsigned char>( diffuse.red() );
149  *fptr++ = static_cast<unsigned char>( diffuse.green() );
150  *fptr++ = static_cast<unsigned char>( diffuse.blue() );
151 
152  *fptr++ = static_cast<unsigned char>( warm.red() );
153  *fptr++ = static_cast<unsigned char>( warm.green() );
154  *fptr++ = static_cast<unsigned char>( warm.blue() );
155 
156  *fptr++ = static_cast<unsigned char>( cool.red() );
157  *fptr++ = static_cast<unsigned char>( cool.green() );
158  *fptr++ = static_cast<unsigned char>( cool.blue() );
159 
160  *fptr++ = static_cast<unsigned char>( specular.red() );
161  *fptr++ = static_cast<unsigned char>( specular.green() );
162  *fptr++ = static_cast<unsigned char>( specular.blue() );
163 
164  return array;
165 }
166 
168 {
169  return 12 * sizeof( unsigned char );
170 }
171 
172 void QgsGoochMaterialSettings::applyDataDefinedToGeometry( Qt3DRender::QGeometry *geometry, int vertexCount, const QByteArray &data ) const
173 {
174  Qt3DRender::QBuffer *dataBuffer = new Qt3DRender::QBuffer( geometry );
175 
176  Qt3DRender::QAttribute *diffuseAttribute = new Qt3DRender::QAttribute( geometry );
177  diffuseAttribute->setName( QStringLiteral( "dataDefinedDiffuseColor" ) );
178  diffuseAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedByte );
179  diffuseAttribute->setVertexSize( 3 );
180  diffuseAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
181  diffuseAttribute->setBuffer( dataBuffer );
182  diffuseAttribute->setByteStride( 12 * sizeof( unsigned char ) );
183  diffuseAttribute->setByteOffset( 0 );
184  diffuseAttribute->setCount( vertexCount );
185  geometry->addAttribute( diffuseAttribute );
186 
187  Qt3DRender::QAttribute *warmAttribute = new Qt3DRender::QAttribute( geometry );
188  warmAttribute->setName( QStringLiteral( "dataDefinedWarmColor" ) );
189  warmAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedByte );
190  warmAttribute->setVertexSize( 3 );
191  warmAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
192  warmAttribute->setBuffer( dataBuffer );
193  warmAttribute->setByteStride( 12 * sizeof( unsigned char ) );
194  warmAttribute->setByteOffset( 3 * sizeof( unsigned char ) );
195  warmAttribute->setCount( vertexCount );
196  geometry->addAttribute( warmAttribute
197  );
198 
199  Qt3DRender::QAttribute *coolAttribute = new Qt3DRender::QAttribute( geometry );
200  coolAttribute->setName( QStringLiteral( "dataDefinedCoolColor" ) );
201  coolAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedByte );
202  coolAttribute->setVertexSize( 3 );
203  coolAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
204  coolAttribute->setBuffer( dataBuffer );
205  coolAttribute->setByteStride( 12 * sizeof( unsigned char ) );
206  coolAttribute->setByteOffset( 6 * sizeof( unsigned char ) );
207  coolAttribute->setCount( vertexCount );
208  geometry->addAttribute( coolAttribute );
209 
210 
211  Qt3DRender::QAttribute *specularAttribute = new Qt3DRender::QAttribute( geometry );
212  specularAttribute->setName( QStringLiteral( "dataDefinedSpecularColor" ) );
213  specularAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedByte );
214  specularAttribute->setVertexSize( 3 );
215  specularAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
216  specularAttribute->setBuffer( dataBuffer );
217  specularAttribute->setByteStride( 12 * sizeof( unsigned char ) );
218  specularAttribute->setByteOffset( 9 * sizeof( unsigned char ) );
219  specularAttribute->setCount( vertexCount );
220  geometry->addAttribute( specularAttribute );
221 
222  dataBuffer->setData( data );
223 }
224 
225 Qt3DRender::QMaterial *QgsGoochMaterialSettings::dataDefinedMaterial() const
226 {
227  Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial;
228 
229  Qt3DRender::QEffect *eff = new Qt3DRender::QEffect( material );
230 
231  Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique;
232  technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
233  technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
234  technique->graphicsApiFilter()->setMajorVersion( 3 );
235  technique->graphicsApiFilter()->setMinorVersion( 3 );
236  Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey();
237  filterKey->setName( QStringLiteral( "renderingStyle" ) );
238  filterKey->setValue( QStringLiteral( "forward" ) );
239  technique->addFilterKey( filterKey );
240 
241  Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass();
242  Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram();
243 
244  //Load shader programs
245  QUrl urlVert( QStringLiteral( "qrc:/shaders/goochDataDefined.vert" ) );
246  shaderProgram->setShaderCode( Qt3DRender::QShaderProgram::Vertex, shaderProgram->loadSource( urlVert ) );
247  QUrl urlFrag( QStringLiteral( "qrc:/shaders/goochDataDefined.frag" ) );
248  shaderProgram->setShaderCode( Qt3DRender::QShaderProgram::Fragment, shaderProgram->loadSource( urlFrag ) );
249 
250  renderPass->setShaderProgram( shaderProgram );
251  technique->addRenderPass( renderPass );
252 
253  technique->addParameter( new Qt3DRender::QParameter( QStringLiteral( "shininess" ), mShininess ) );
254  technique->addParameter( new Qt3DRender::QParameter( QStringLiteral( "alpha" ), mAlpha ) );
255  technique->addParameter( new Qt3DRender::QParameter( QStringLiteral( "beta" ), mBeta ) );
256 
257  eff->addTechnique( technique );
258  material->setEffect( eff );
259 
260  return material;
261 }
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.
@ Warm
Warm color (gooch material)
@ Cool
Cool color (gooch material)
QgsPropertyCollection dataDefinedProperties() const
Returns the symbol material property collection, used for data defined overrides.
QColor valueAsColor(int key, const QgsExpressionContext &context, const QColor &defaultColor=QColor(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a color.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsGoochMaterialSettings * clone() const override
Clones the material settings.
QColor specular() const
Returns specular color component.
QColor cool() const
Returns cool color component.
int dataDefinedByteStride() const override
Returns byte stride of the data defined colors,used to fill the vertex colors data defined buffer for...
QByteArray dataDefinedVertexColorsAsByte(const QgsExpressionContext &expressionContext) const override
Returns byte array corresponding to the data defined colors depending of the expressionContext,...
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const override
Writes settings to a DOM element.
QMap< QString, QString > toExportParameters() const override
Returns the parameters to be exported to .mtl file.
QColor warm() const
Returns warm color component.
QString type() const override
Returns the unique type name for the material.
QColor diffuse() const
Returns diffuse color component.
QgsGoochMaterialSettings()=default
Constructor for QgsGoochMaterialSettings.
void addParametersToEffect(Qt3DRender::QEffect *effect) const override
Adds parameters from the material to a destination effect.
static QgsAbstractMaterialSettings * create()
Returns a new instance of QgsGoochMaterialSettings.
static bool supportsTechnique(QgsMaterialSettingsRenderingTechnique technique)
Returns true if the specified technique is supported by the Gooch material.
Qt3DRender::QMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const override
Creates a new QMaterial object representing the material settings.
void applyDataDefinedToGeometry(Qt3DRender::QGeometry *geometry, int vertexCount, const QByteArray &data) const override
Applies the data defined bytes, dataDefinedBytes, on the geometry by filling a specific vertex buffer...
void readXml(const QDomElement &elem, const QgsReadWriteContext &context) override
Reads settings from a DOM element.
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.
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)