QGIS API Documentation 3.99.0-Master (357b655ed83)
Loading...
Searching...
No Matches
qgs3daxisrenderview.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgs3daxisrenderview.cpp
3 --------------------------------------
4 Date : June 2024
5 Copyright : (C) 2024 by Benoit De Mezzo
6 Email : benoit dot de dot mezzo at oslandia 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
16#include "qgs3daxisrenderview.h"
17
18#include "qgs3daxis.h"
19#include "qgs3dmapcanvas.h"
20#include "qgs3dmapsettings.h"
21#include "qgscameracontroller.h"
22#include "qgsframegraph.h"
23#include "qgsmapsettings.h"
24
25#include <QScreen>
26#include <QVector2D>
27#include <QVector3D>
28#include <Qt3DCore/QBuffer>
29#include <Qt3DCore/QEntity>
30#include <Qt3DExtras/QText2DEntity>
31#include <Qt3DRender/QCamera>
32#include <Qt3DRender/QGeometryRenderer>
33#include <Qt3DRender/QLayer>
34#include <Qt3DRender/QPickEvent>
35#include <Qt3DRender/QScreenRayCaster>
36#include <Qt3DRender/QSortPolicy>
37#include <Qt3DRender/QViewport>
38#include <Qt3DRender/qsubtreeenabler.h>
39
40Qgs3DAxisRenderView::Qgs3DAxisRenderView( const QString &viewName, Qgs3DMapCanvas *canvas, //
41 QgsCameraController *cameraCtrl, Qgs3DMapSettings *settings, //
42 Qgs3DAxis *axis3D )
43 : QgsAbstractRenderView( viewName )
44 , mCanvas( canvas )
45 , mMapSettings( settings )
46 , m3DAxis( axis3D )
47{
48 mViewport = new Qt3DRender::QViewport( mRendererEnabler );
49 mViewport->setObjectName( mViewName + "::Viewport" );
50
51 mObjectLayer = new Qt3DRender::QLayer;
52 mObjectLayer->setObjectName( mViewName + "::ObjectLayer" );
53 mObjectLayer->setRecursive( true );
54
55 mLabelLayer = new Qt3DRender::QLayer;
56 mLabelLayer->setObjectName( mViewName + "::LabelLayer" );
57 mLabelLayer->setRecursive( true );
58
59 // render pass for the object (axis or cube)
60 Qt3DRender::QLayerFilter *objectFilter = new Qt3DRender::QLayerFilter( mViewport );
61 objectFilter->addLayer( mObjectLayer );
62
63 mObjectCamera = new Qt3DRender::QCamera;
64 mObjectCamera->setObjectName( mViewName + "::ObjectCamera" );
65 mObjectCamera->setProjectionType( cameraCtrl->camera()->projectionType() );
66 mObjectCamera->lens()->setFieldOfView( cameraCtrl->camera()->lens()->fieldOfView() * 0.5f );
67
68 Qt3DRender::QCameraSelector *cameraSelector = new Qt3DRender::QCameraSelector( objectFilter );
69 cameraSelector->setCamera( mObjectCamera );
70
71 // This ensures to have the label (Text2DEntity) rendered after the other objects and therefore
72 // avoid any transparency issue on the label.
73 Qt3DRender::QSortPolicy *objectSortPolicy = new Qt3DRender::QSortPolicy( cameraSelector );
74 QVector<Qt3DRender::QSortPolicy::SortType> objectSortTypes = QVector<Qt3DRender::QSortPolicy::SortType>();
75 objectSortTypes << Qt3DRender::QSortPolicy::BackToFront;
76 objectSortPolicy->setSortTypes( objectSortTypes );
77
78 Qt3DRender::QClearBuffers *objectClearBuffers = new Qt3DRender::QClearBuffers( objectSortPolicy );
79 objectClearBuffers->setBuffers( Qt3DRender::QClearBuffers::DepthBuffer );
80
81 Qt3DRender::QLayerFilter *labelFilter = new Qt3DRender::QLayerFilter( mViewport );
82 labelFilter->addLayer( mLabelLayer );
83
84 mLabelCamera = new Qt3DRender::QCamera;
85 mLabelCamera->setObjectName( mViewName + "::LabelCamera" );
86 mLabelCamera->setProjectionType( Qt3DRender::QCameraLens::ProjectionType::OrthographicProjection );
87
88 Qt3DRender::QCameraSelector *labelCameraSelector = new Qt3DRender::QCameraSelector( labelFilter );
89 labelCameraSelector->setCamera( mLabelCamera );
90
91 // this ensures to have the label (Text2DEntity) rendered after the other objects and therefore
92 // avoid any transparency issue on the label.
93 Qt3DRender::QSortPolicy *labelSortPolicy = new Qt3DRender::QSortPolicy( labelCameraSelector );
94 QVector<Qt3DRender::QSortPolicy::SortType> labelSortTypes = QVector<Qt3DRender::QSortPolicy::SortType>();
95 labelSortTypes << Qt3DRender::QSortPolicy::BackToFront;
96 labelSortPolicy->setSortTypes( labelSortTypes );
97
98 Qt3DRender::QClearBuffers *clearBuffers = new Qt3DRender::QClearBuffers( labelSortPolicy );
99 clearBuffers->setBuffers( Qt3DRender::QClearBuffers::DepthBuffer );
100
101 // update viewport size
103}
104
105Qt3DRender::QViewport *Qgs3DAxisRenderView::viewport() const
106{
107 return mViewport;
108}
109
110Qt3DRender::QLayer *Qgs3DAxisRenderView::objectLayer() const
111{
112 return mObjectLayer;
113}
114
115Qt3DRender::QLayer *Qgs3DAxisRenderView::labelLayer() const
116{
117 return mLabelLayer;
118}
119
120Qt3DRender::QCamera *Qgs3DAxisRenderView::objectCamera() const
121{
122 return mObjectCamera;
123}
124
125Qt3DRender::QCamera *Qgs3DAxisRenderView::labelCamera() const
126{
127 return mLabelCamera;
128}
129
130void Qgs3DAxisRenderView::updateWindowResize( int width, int height )
131{
132 onViewportSizeUpdate( width, height );
133}
134
135
136void Qgs3DAxisRenderView::onViewportSizeUpdate( int width, int height )
137{
138 Qgs3DAxisSettings settings = mMapSettings->get3DAxisSettings();
139 double windowWidth = static_cast<double>( width < 0 ? mCanvas->width() : width );
140 double windowHeight = static_cast<double>( height < 0 ? mCanvas->height() : height );
141
142 if ( 2 <= QgsLogger::debugLevel() )
143 {
144 QgsMapSettings set;
145 QgsDebugMsgLevel( QString( "onViewportSizeUpdate window w/h: %1px / %2px" ).arg( windowWidth ).arg( windowHeight ), 2 );
146 QgsDebugMsgLevel( QString( "onViewportSizeUpdate window physicalDpi %1 (%2, %3)" ).arg( mCanvas->screen()->physicalDotsPerInch() ).arg( mCanvas->screen()->physicalDotsPerInchX() ).arg( mCanvas->screen()->physicalDotsPerInchY() ), 2 );
147 QgsDebugMsgLevel( QString( "onViewportSizeUpdate window logicalDotsPerInch %1 (%2, %3)" ).arg( mCanvas->screen()->logicalDotsPerInch() ).arg( mCanvas->screen()->logicalDotsPerInchX() ).arg( mCanvas->screen()->logicalDotsPerInchY() ), 2 );
148
149 QgsDebugMsgLevel( QString( "onViewportSizeUpdate window pixel ratio %1" ).arg( mCanvas->screen()->devicePixelRatio() ), 2 );
150
151 QgsDebugMsgLevel( QString( "onViewportSizeUpdate set pixel ratio %1" ).arg( set.devicePixelRatio() ), 2 );
152 QgsDebugMsgLevel( QString( "onViewportSizeUpdate set outputDpi %1" ).arg( set.outputDpi() ), 2 );
153 QgsDebugMsgLevel( QString( "onViewportSizeUpdate set dpiTarget %1" ).arg( set.dpiTarget() ), 2 );
154 }
155
156 // default viewport size in pixel according to 92 dpi
157 double defaultViewportPixelSize = ( ( double ) settings.defaultViewportSize() / 25.4 ) * 92.0;
158
159 // computes the viewport size according to screen dpi but as the viewport size growths too fast
160 // then we limit the growth by using a factor on the dpi difference.
161 double viewportPixelSize = defaultViewportPixelSize + ( ( double ) settings.defaultViewportSize() / 25.4 ) * ( mCanvas->screen()->physicalDotsPerInch() - 92.0 ) * 0.7;
162 QgsDebugMsgLevel( QString( "onViewportSizeUpdate viewportPixelSize %1" ).arg( viewportPixelSize ), 2 );
163 double widthRatio = viewportPixelSize / windowWidth;
164 double heightRatio = widthRatio * windowWidth / windowHeight;
165
166 QgsDebugMsgLevel( QString( "3DAxis viewport ratios width: %1% / height: %2%" ).arg( widthRatio * 100.0 ).arg( heightRatio * 100.0 ), 2 );
167
168 if ( heightRatio * windowHeight < viewportPixelSize )
169 {
170 heightRatio = viewportPixelSize / windowHeight;
171 widthRatio = heightRatio * windowHeight / windowWidth;
172 QgsDebugMsgLevel( QString( "3DAxis viewport, height too small, ratios adjusted to width: %1% / height: %2%" ).arg( widthRatio * 100.0 ).arg( heightRatio * 100.0 ), 2 );
173 }
174
175 if ( heightRatio > settings.maxViewportRatio() || widthRatio > settings.maxViewportRatio() )
176 {
177 QgsDebugMsgLevel( QString( "3DAxis viewport takes too much place into the 3d view, disabling it (maxViewportRatio: %1)." ).arg( settings.maxViewportRatio() ), 2 );
178 // take too much place into the 3d view
179 mViewport->setEnabled( false );
180 m3DAxis->onViewportScaleFactorChanged( 0.0 );
181 }
182 else
183 {
184 if ( !mViewport->isEnabled() )
185 {
186 // will be used to adjust the axis label translations/sizes
187 m3DAxis->onViewportScaleFactorChanged( viewportPixelSize / defaultViewportPixelSize );
188 }
189 mViewport->setEnabled( true );
190
191 float xRatio = 1.0f;
192 float yRatio = 1.0f;
193 if ( settings.horizontalPosition() == Qt::AnchorPoint::AnchorLeft )
194 xRatio = 0.0f;
195 else if ( settings.horizontalPosition() == Qt::AnchorPoint::AnchorHorizontalCenter )
196 xRatio = 0.5f - static_cast<float>( widthRatio ) / 2.0f;
197 else
198 xRatio = 1.0f - static_cast<float>( widthRatio );
199
200 if ( settings.verticalPosition() == Qt::AnchorPoint::AnchorTop )
201 yRatio = 0.0f;
202 else if ( settings.verticalPosition() == Qt::AnchorPoint::AnchorVerticalCenter )
203 yRatio = 0.5f - static_cast<float>( heightRatio ) / 2.0f;
204 else
205 yRatio = 1.0f - static_cast<float>( heightRatio );
206
207 QgsDebugMsgLevel( QString( "Qgs3DAxis: update viewport: %1 x %2 x %3 x %4" ).arg( xRatio ).arg( yRatio ).arg( widthRatio ).arg( heightRatio ), 2 );
208 mViewport->setNormalizedRect( QRectF( xRatio, yRatio, widthRatio, heightRatio ) );
209
210 if ( settings.mode() == Qgs3DAxisSettings::Mode::Crs )
211 {
212 const float halfWidthSize = static_cast<float>( windowWidth * widthRatio / 2.0 );
213 const float halfHeightSize = static_cast<float>( windowWidth * widthRatio / 2.0 );
214 mLabelCamera->lens()->setOrthographicProjection(
215 -halfWidthSize, halfWidthSize,
216 -halfHeightSize, halfHeightSize,
217 mLabelCamera->lens()->nearPlane(), mLabelCamera->lens()->farPlane()
218 );
219 }
220 }
221}
222
224{
225 Qgs3DAxisSettings axisSettings = mMapSettings->get3DAxisSettings();
226 axisSettings.setHorizontalPosition( pos );
227 mMapSettings->set3DAxisSettings( axisSettings );
229}
230
232{
233 Qgs3DAxisSettings axisSettings = mMapSettings->get3DAxisSettings();
234 axisSettings.setVerticalPosition( pos );
235 mMapSettings->set3DAxisSettings( axisSettings );
237}
Qt3DRender::QLayer * labelLayer() const
Returns the layer to be used by entities to be included in the label renderpass.
void onVerticalPositionChanged(Qt::AnchorPoint position)
Updates viewport vertical position.
Qt3DRender::QCamera * labelCamera() const
Returns camera used for billboarded labels.
Qt3DRender::QLayer * objectLayer() const
Returns main object layer.
Qgs3DAxisRenderView(const QString &viewName, Qgs3DMapCanvas *canvas, QgsCameraController *cameraCtrl, Qgs3DMapSettings *settings, Qgs3DAxis *axis3D)
Constructor for Qgs3DAxisRenderView with the specified parent object.
Qt3DRender::QViewport * viewport() const
Returns the viewport associated to this renderview.
void onViewportSizeUpdate(int width=-1, int height=-1)
Updates viewport size. Uses canvas size by default.
Qt3DRender::QCamera * objectCamera() const
Returns main object camera (used for axis or cube).
void updateWindowResize(int width, int height) override
Called when 3D window is resized.
void onHorizontalPositionChanged(Qt::AnchorPoint position)
Updates viewport horizontal position.
Contains the configuration of a 3d axis.
double maxViewportRatio() const
Returns the maximal axis viewport ratio (see Qt3DRender::QViewport::normalizedRect()).
@ Crs
Respect CRS directions.
Qt::AnchorPoint verticalPosition() const
Returns the vertical position for the 3d axis.
void setHorizontalPosition(Qt::AnchorPoint position)
Sets the horizontal position for the 3d axis.
int defaultViewportSize() const
Returns the default axis viewport size in millimeters.
Qgs3DAxisSettings::Mode mode() const
Returns the type of the 3daxis.
Qt::AnchorPoint horizontalPosition() const
Returns the horizontal position for the 3d axis.
void setVerticalPosition(Qt::AnchorPoint position)
Sets the vertical position for the 3d axis.
Display 3D ortho axis in the main 3D view.
Definition qgs3daxis.h:51
Convenience wrapper to simplify the creation of a 3D window ready to be used with QGIS.
Definition of the world.
Qt3DRender::QSubtreeEnabler * mRendererEnabler
QgsAbstractRenderView(const QString &viewName)
Constructor for QgsAbstractRenderView with the specified parent object.
Object that controls camera movement based on user input.
Qt3DRender::QCamera * camera() const
Returns camera that is being controlled.
static int debugLevel()
Reads the environment variable QGIS_DEBUG and converts it to int.
Definition qgslogger.h:146
Contains configuration for rendering maps.
double dpiTarget() const
Returns the target DPI (dots per inch) to be taken into consideration when rendering.
float devicePixelRatio() const
Returns the device pixel ratio.
double outputDpi() const
Returns the DPI (dots per inch) used for conversion between real world units (e.g.
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63