QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
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 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
175  Qt3DRender::QBuffer *dataBuffer = new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer, geometry );
176 #else
177  Qt3DRender::QBuffer *dataBuffer = new Qt3DRender::QBuffer( geometry );
178 #endif
179 
180  Qt3DRender::QAttribute *diffuseAttribute = new Qt3DRender::QAttribute( geometry );
181  diffuseAttribute->setName( QStringLiteral( "dataDefinedDiffuseColor" ) );
182  diffuseAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedByte );
183  diffuseAttribute->setVertexSize( 3 );
184  diffuseAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
185  diffuseAttribute->setBuffer( dataBuffer );
186  diffuseAttribute->setByteStride( 12 * sizeof( unsigned char ) );
187  diffuseAttribute->setByteOffset( 0 );
188  diffuseAttribute->setCount( vertexCount );
189  geometry->addAttribute( diffuseAttribute );
190 
191  Qt3DRender::QAttribute *warmAttribute = new Qt3DRender::QAttribute( geometry );
192  warmAttribute->setName( QStringLiteral( "dataDefinedWarmColor" ) );
193  warmAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedByte );
194  warmAttribute->setVertexSize( 3 );
195  warmAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
196  warmAttribute->setBuffer( dataBuffer );
197  warmAttribute->setByteStride( 12 * sizeof( unsigned char ) );
198  warmAttribute->setByteOffset( 3 * sizeof( unsigned char ) );
199  warmAttribute->setCount( vertexCount );
200  geometry->addAttribute( warmAttribute
201  );
202 
203  Qt3DRender::QAttribute *coolAttribute = new Qt3DRender::QAttribute( geometry );
204  coolAttribute->setName( QStringLiteral( "dataDefinedCoolColor" ) );
205  coolAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedByte );
206  coolAttribute->setVertexSize( 3 );
207  coolAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
208  coolAttribute->setBuffer( dataBuffer );
209  coolAttribute->setByteStride( 12 * sizeof( unsigned char ) );
210  coolAttribute->setByteOffset( 6 * sizeof( unsigned char ) );
211  coolAttribute->setCount( vertexCount );
212  geometry->addAttribute( coolAttribute );
213 
214 
215  Qt3DRender::QAttribute *specularAttribute = new Qt3DRender::QAttribute( geometry );
216  specularAttribute->setName( QStringLiteral( "dataDefinedSpecularColor" ) );
217  specularAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedByte );
218  specularAttribute->setVertexSize( 3 );
219  specularAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
220  specularAttribute->setBuffer( dataBuffer );
221  specularAttribute->setByteStride( 12 * sizeof( unsigned char ) );
222  specularAttribute->setByteOffset( 9 * sizeof( unsigned char ) );
223  specularAttribute->setCount( vertexCount );
224  geometry->addAttribute( specularAttribute );
225 
226  dataBuffer->setData( data );
227 }
228 
229 Qt3DRender::QMaterial *QgsGoochMaterialSettings::dataDefinedMaterial() const
230 {
231  Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial;
232 
233  Qt3DRender::QEffect *eff = new Qt3DRender::QEffect( material );
234 
235  Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique;
236  technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
237  technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
238  technique->graphicsApiFilter()->setMajorVersion( 3 );
239  technique->graphicsApiFilter()->setMinorVersion( 3 );
240  Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey();
241  filterKey->setName( QStringLiteral( "renderingStyle" ) );
242  filterKey->setValue( QStringLiteral( "forward" ) );
243  technique->addFilterKey( filterKey );
244 
245  Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass();
246  Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram();
247 
248  //Load shader programs
249  QUrl urlVert( QStringLiteral( "qrc:/shaders/goochDataDefined.vert" ) );
250  shaderProgram->setShaderCode( Qt3DRender::QShaderProgram::Vertex, shaderProgram->loadSource( urlVert ) );
251  QUrl urlFrag( QStringLiteral( "qrc:/shaders/goochDataDefined.frag" ) );
252  shaderProgram->setShaderCode( Qt3DRender::QShaderProgram::Fragment, shaderProgram->loadSource( urlFrag ) );
253 
254  renderPass->setShaderProgram( shaderProgram );
255  technique->addRenderPass( renderPass );
256 
257  technique->addParameter( new Qt3DRender::QParameter( QStringLiteral( "shininess" ), mShininess ) );
258  technique->addParameter( new Qt3DRender::QParameter( QStringLiteral( "alpha" ), mAlpha ) );
259  technique->addParameter( new Qt3DRender::QParameter( QStringLiteral( "beta" ), mBeta ) );
260 
261  eff->addTechnique( technique );
262  material->setEffect( eff );
263 
264  return material;
265 }
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)