QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgspoint3dbillboardmaterial.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspoint3dbillboardmaterial.h
3  --------------------------------------
4  Date : Jul 2019
5  Copyright : (C) 2019 by Ismail Sunni
6  Email : imajimatika 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 #include <Qt3DRender/QParameter>
16 #include <Qt3DRender/QShaderProgram>
17 #include <Qt3DRender/QRenderPass>
18 #include <Qt3DRender/QTechnique>
19 #include <Qt3DRender/QGraphicsApiFilter>
20 #include <Qt3DRender/QEffect>
21 #include <Qt3DRender/QBlendEquationArguments>
22 #include <Qt3DRender/QBlendEquation>
23 #include <Qt3DRender/QNoDepthMask>
24 #include <QUrl>
25 
26 #include "qgslogger.h"
29 #include "qgsmarkersymbollayer.h"
30 #include "qgssymbollayerutils.h"
31 #include "qgssettings.h"
32 #include "qgs3dmapsettings.h"
33 #include "qgsmarkersymbol.h"
34 
36  : mSize( new Qt3DRender::QParameter( "BB_SIZE", QSizeF( 100, 100 ), this ) )
37  , mViewportSize( new Qt3DRender::QParameter( "WIN_SCALE", QSizeF( 800, 600 ), this ) )
38 {
39  addParameter( mSize );
40  addParameter( mViewportSize );
41 
42  // Initialize with empty parameter.
43  mTexture2D = new Qt3DRender::QParameter( "tex0", QVariant(), this );
44  addParameter( mTexture2D );
45 
46  // Blending for handling transparency
47  Qt3DRender::QBlendEquationArguments *blendState = new Qt3DRender::QBlendEquationArguments;
48  blendState->setSourceRgb( Qt3DRender::QBlendEquationArguments::SourceAlpha );
49  blendState->setDestinationRgb( Qt3DRender::QBlendEquationArguments::OneMinusSourceAlpha );
50 
51  Qt3DRender::QBlendEquation *blendEquation = new Qt3DRender::QBlendEquation;
52  blendEquation->setBlendFunction( Qt3DRender::QBlendEquation::Add );
53 
54  // Shader program
55  Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram( this );
56  shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/billboards.vert" ) ) ) );
57  shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/billboards.frag" ) ) ) );
58  shaderProgram->setGeometryShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/billboards.geom" ) ) ) );
59 
60  // Render Pass
61  Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass( this );
62  renderPass->setShaderProgram( shaderProgram );
63  renderPass->addRenderState( blendState );
64  renderPass->addRenderState( blendEquation );
65 
66  // without this filter the default forward renderer would not render this
67  Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey;
68  filterKey->setName( QStringLiteral( "renderingStyle" ) );
69  filterKey->setValue( "forward" );
70 
71  // Technique
72  Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique;
73  technique->addRenderPass( renderPass );
74  technique->addFilterKey( filterKey );
75  technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
76  technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
77  technique->graphicsApiFilter()->setMajorVersion( 3 );
78  technique->graphicsApiFilter()->setMinorVersion( 1 );
79 
80  // Effect
81  Qt3DRender::QEffect *effect = new Qt3DRender::QEffect( this );
82  effect->addTechnique( technique );
83 
84  setEffect( effect );
85 }
86 
87 void QgsPoint3DBillboardMaterial::setSize( const QSizeF size )
88 {
89  mSize->setValue( size );
90 }
91 
93 {
94  return mSize->value().value<QSizeF>();
95 }
96 
98 {
99  mViewportSize->setValue( size );
100 }
101 
103 {
104  return mViewportSize->value().value<QSizeF>();
105 }
106 
107 void QgsPoint3DBillboardMaterial::setTexture2DFromImage( QImage image, double size )
108 {
109  // Create texture image
110  const QgsRectangle randomExtent = QgsRectangle( rand(), rand(), rand(), rand() );
111  QgsTerrainTextureImage *billboardTextureImage = new QgsTerrainTextureImage( image, randomExtent, QStringLiteral( "billboard material." ) );
112 
113  setTexture2DFromTextureImage( billboardTextureImage );
114  setSize( QSizeF( size + size, size + size ) );
115 }
116 
118 {
119  // Default texture
120  const std::unique_ptr< QgsMarkerSymbol> defaultSymbol( static_cast<QgsMarkerSymbol *>( QgsSymbol::defaultSymbol( QgsWkbTypes::PointGeometry ) ) );
121  setTexture2DFromSymbol( defaultSymbol.get(), map, selected );
122 }
123 
125 {
126  QgsRenderContext context;
127  context.setSelectionColor( map.selectionColor() );
128  context.setScaleFactor( map.outputDpi() / 25.4 );
129  const double pixelSize = context.convertToPainterUnits( markerSymbol->size( context ), markerSymbol->sizeUnit() );
130 
131  // This number is an max estimation ratio between stroke width and symbol size.
132  const double strokeRatio = 0.5;
133  // Minimum extra width, just in case the size is small, but the stroke is quite big.
134  // 10 mm is quite big based on Raymond's experiece.
135  // 10 mm has around 37 pixel in 96 dpi, round up become 40.
136  const double minimumExtraSize = 40;
137  const double extraPixel = minimumExtraSize > pixelSize * strokeRatio ? minimumExtraSize : pixelSize * strokeRatio;
138  const int pixelWithExtra = std::ceil( pixelSize + extraPixel );
139  const QPixmap symbolPixmap = QgsSymbolLayerUtils::symbolPreviewPixmap( markerSymbol, QSize( pixelWithExtra, pixelWithExtra ), 0, &context, selected );
140  const QImage symbolImage = symbolPixmap.toImage();
141  const QImage flippedSymbolImage = symbolImage.mirrored();
142  setTexture2DFromImage( flippedSymbolImage, pixelWithExtra );
143 }
144 
145 void QgsPoint3DBillboardMaterial::setTexture2DFromTextureImage( Qt3DRender::QAbstractTextureImage *textureImage )
146 {
147  // Texture2D
148  Qt3DRender::QTexture2D *texture2D = new Qt3DRender::QTexture2D( this );
149  texture2D->setGenerateMipMaps( false );
150  texture2D->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
151  texture2D->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
152 
153  // The textureImage gets parented to texture2D here
154  texture2D->addTextureImage( textureImage );
155 
156  mTexture2D->setValue( QVariant::fromValue( texture2D ) );
157 }
QgsSymbol::defaultSymbol
static QgsSymbol * defaultSymbol(QgsWkbTypes::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Definition: qgssymbol.cpp:673
Qgs3DMapSettings::selectionColor
QColor selectionColor() const
Returns color used for selected features.
Definition: qgs3dmapsettings.cpp:527
Qgs3DMapSettings::outputDpi
double outputDpi() const
Returns DPI used for conversion between real world units (e.g.
Definition: qgs3dmapsettings.h:519
QgsPoint3DBillboardMaterial::setViewportSize
void setViewportSize(const QSizeF size)
Set the size of the view port.
Definition: qgspoint3dbillboardmaterial.cpp:97
QgsMarkerSymbol::size
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
Definition: qgsmarkersymbol.cpp:197
QgsPoint3DBillboardMaterial::setTexture2DFromSymbol
void setTexture2DFromSymbol(QgsMarkerSymbol *markerSymbol, const Qgs3DMapSettings &map, bool selected=false)
Set markerSymbol for the texture with map and selected parameter for rendering.
Definition: qgspoint3dbillboardmaterial.cpp:124
qgssymbollayerutils.h
qgsmarkersymbollayer.h
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:59
qgspoint3dbillboardmaterial.h
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsPoint3DBillboardMaterial::QgsPoint3DBillboardMaterial
QgsPoint3DBillboardMaterial()
Definition: qgspoint3dbillboardmaterial.cpp:35
QgsSymbolLayerUtils::symbolPreviewPixmap
static QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *shape=nullptr)
Returns a pixmap preview for a color ramp.
Definition: qgssymbollayerutils.cpp:876
QgsMarkerSymbol
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgsmarkersymbol.h:30
qgsterraintextureimage_p.h
Qt3DRender
Definition: qgs3dmapscene.h:28
Qgs3DMapSettings
Definition of the world.
Definition: qgs3dmapsettings.h:57
QgsRenderContext::setSelectionColor
void setSelectionColor(const QColor &color)
Sets the color to use when rendering selected features.
Definition: qgsrendercontext.h:561
QgsRenderContext::convertToPainterUnits
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
Definition: qgsrendercontext.cpp:367
qgs3dmapsettings.h
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:142
qgsmarkersymbol.h
qgssettings.h
QgsPoint3DBillboardMaterial::setSize
void setSize(const QSizeF size)
Set the billboard size.
Definition: qgspoint3dbillboardmaterial.cpp:87
QgsMarkerSymbol::sizeUnit
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the size units for the whole symbol (including all symbol layers).
Definition: qgsmarkersymbol.cpp:254
qgslogger.h
QgsRenderContext::setScaleFactor
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
Definition: qgsrendercontext.h:472
QgsPoint3DBillboardMaterial::useDefaultSymbol
void useDefaultSymbol(const Qgs3DMapSettings &map, bool selected=false)
Set default symbol for the texture with map and selected parameter for rendering.
Definition: qgspoint3dbillboardmaterial.cpp:117
QgsPoint3DBillboardMaterial::windowSize
QSizeF windowSize() const
Returns the size of the view port.
Definition: qgspoint3dbillboardmaterial.cpp:102
QgsPoint3DBillboardMaterial::size
QSizeF size() const
Returns the billboard size.
Definition: qgspoint3dbillboardmaterial.cpp:92