diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3871987b1db..e0ed8410a31 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -284,6 +284,7 @@ IF(WITH_CORE)
FIND_PACKAGE(Qt53DInput REQUIRED)
FIND_PACKAGE(Qt53DLogic REQUIRED)
FIND_PACKAGE(Qt53DExtras REQUIRED)
+ SET(HAVE_3D TRUE) # used in qgsconfig.h
ENDIF (WITH_3D)
INCLUDE("cmake/modules/ECMQt4To5Porting.cmake")
MESSAGE(STATUS "Found Qt version: ${Qt5Core_VERSION_STRING}")
diff --git a/cmake_templates/qgsconfig.h.in b/cmake_templates/qgsconfig.h.in
index 102f3a2d979..99007f6d596 100644
--- a/cmake_templates/qgsconfig.h.in
+++ b/cmake_templates/qgsconfig.h.in
@@ -13,7 +13,7 @@
//used in vim src/core/qgis.cpp
//The way below should work but it resolves to a number like 0110 which the compiler treats as octal I think
//because debuggin it out shows the decimal number 72 which results in incorrect version status.
-//As a short term fix I (Tim) am defining the version in top level cmake. It would be good to
+//As a short term fix I (Tim) am defining the version in top level cmake. It would be good to
//reinstate this more generic approach below at some point though
//#define VERSION_INT ${CPACK_PACKAGE_VERSION_MAJOR}${CPACK_PACKAGE_VERSION_MINOR}${CPACK_PACKAGE_VERSION_PATCH}
#define VERSION_INT ${QGIS_VERSION_INT}
@@ -58,5 +58,7 @@
#cmakedefine ENABLE_MODELTEST
+#cmakedefine HAVE_3D
+
#endif
diff --git a/images/images.qrc b/images/images.qrc
index 535490fc61f..dbbd34252f2 100644
--- a/images/images.qrc
+++ b/images/images.qrc
@@ -570,6 +570,7 @@
themes/default/mGeoPackage.svg
themes/default/mActionAddGeoPackageLayer.svg
icons/qgis_icon.svg
+ themes/default/3d.svg
qgis_tips/symbol_levels.png
diff --git a/images/themes/default/3d.svg b/images/themes/default/3d.svg
new file mode 100644
index 00000000000..330ea19e678
--- /dev/null
+++ b/images/themes/default/3d.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/python/core/qgsapplication.sip b/python/core/qgsapplication.sip
index 8f051af9ceb..17aa06c84d2 100644
--- a/python/core/qgsapplication.sip
+++ b/python/core/qgsapplication.sip
@@ -704,6 +704,7 @@ Returns path to the build output directory. Valid only when running from build d
:rtype: QgsFieldFormatterRegistry
%End
+
static QString nullRepresentation();
%Docstring
This string is used to represent the value `NULL` throughout QGIS.
diff --git a/python/core/qgsmaplayer.sip b/python/core/qgsmaplayer.sip
index e6e45cdebaa..be3c0691ad9 100644
--- a/python/core/qgsmaplayer.sip
+++ b/python/core/qgsmaplayer.sip
@@ -754,6 +754,8 @@ Return pointer to layer's undo stack
:rtype: QgsMapLayerStyleManager
%End
+
+
bool isInScaleRange( double scale ) const;
%Docstring
Tests whether the layer should be visible at the specified ``scale``.
@@ -1014,6 +1016,12 @@ Signal emitted when the blend mode is changed, through QgsMapLayer.setBlendMode(
%Docstring
Signal emitted when legend of the layer has changed
.. versionadded:: 2.6
+%End
+
+ void renderer3DChanged();
+%Docstring
+ Signal emitted when 3D renderer associated with the layer has changed.
+.. versionadded:: 3.0
%End
void configChanged();
diff --git a/src/3d/CMakeLists.txt b/src/3d/CMakeLists.txt
index 711bd596f73..87000714393 100644
--- a/src/3d/CMakeLists.txt
+++ b/src/3d/CMakeLists.txt
@@ -2,7 +2,6 @@
# sources
SET(QGIS_3D_SRCS
- abstract3drenderer.cpp
abstract3dsymbol.cpp
cameracontroller.cpp
lineentity.cpp
@@ -15,6 +14,7 @@ SET(QGIS_3D_SRCS
tessellator.cpp
tilingscheme.cpp
utils.cpp
+ vectorlayer3drenderer.cpp
chunks/chunkboundsentity.cpp
chunks/chunkedentity.cpp
@@ -63,7 +63,6 @@ QT5_ADD_RESOURCES(QGIS_3D_RCC_SRCS shaders.qrc)
SET(QGIS_3D_HDRS
aabb.h
- abstract3drenderer.h
abstract3dsymbol.h
cameracontroller.h
lineentity.h
@@ -76,6 +75,7 @@ SET(QGIS_3D_HDRS
tessellator.h
tilingscheme.h
utils.h
+ vectorlayer3drenderer.h
chunks/chunkboundsentity.h
chunks/chunkedentity.h
@@ -105,6 +105,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/src/core/symbology-ng
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/expression
+ ${CMAKE_SOURCE_DIR}/src/core/3d
${CMAKE_BINARY_DIR}/src/core
${CMAKE_BINARY_DIR}/src/3d
)
diff --git a/src/3d/map3d.cpp b/src/3d/map3d.cpp
index 375d82b5027..a0a24f787a6 100644
--- a/src/3d/map3d.cpp
+++ b/src/3d/map3d.cpp
@@ -1,9 +1,9 @@
#include "map3d.h"
-#include "abstract3drenderer.h"
#include "flatterraingenerator.h"
#include "demterraingenerator.h"
//#include "quantizedmeshterraingenerator.h"
+#include "vectorlayer3drenderer.h"
#include
#include
@@ -44,7 +44,7 @@ Map3D::Map3D( const Map3D &other )
, mShowTerrainTileInfo( other.mShowTerrainTileInfo )
, mLayers( other.mLayers )
{
- Q_FOREACH ( Abstract3DRenderer *renderer, other.renderers )
+ Q_FOREACH ( QgsAbstract3DRenderer *renderer, other.renderers )
{
renderers << renderer->clone();
}
@@ -108,7 +108,7 @@ void Map3D::readXml( const QDomElement &elem, const QgsReadWriteContext &context
QDomElement elemRenderer = elemRenderers.firstChildElement( "renderer" );
while ( !elemRenderer.isNull() )
{
- Abstract3DRenderer *renderer = nullptr;
+ QgsAbstract3DRenderer *renderer = nullptr;
QString type = elemRenderer.attribute( "type" );
if ( type == "vector" )
{
@@ -167,7 +167,7 @@ QDomElement Map3D::writeXml( QDomDocument &doc, const QgsReadWriteContext &conte
elem.appendChild( elemTerrain );
QDomElement elemRenderers = doc.createElement( "renderers" );
- Q_FOREACH ( const Abstract3DRenderer *renderer, renderers )
+ Q_FOREACH ( const QgsAbstract3DRenderer *renderer, renderers )
{
QDomElement elemRenderer = doc.createElement( "renderer" );
elemRenderer.setAttribute( "type", renderer->type() );
@@ -203,7 +203,7 @@ void Map3D::resolveReferences( const QgsProject &project )
for ( int i = 0; i < renderers.count(); ++i )
{
- Abstract3DRenderer *renderer = renderers[i];
+ QgsAbstract3DRenderer *renderer = renderers[i];
renderer->resolveReferences( project );
}
}
diff --git a/src/3d/map3d.h b/src/3d/map3d.h
index 2d79724a1e7..f18f3486ceb 100644
--- a/src/3d/map3d.h
+++ b/src/3d/map3d.h
@@ -13,7 +13,7 @@
class QgsMapLayer;
class QgsRasterLayer;
-class Abstract3DRenderer;
+class QgsAbstract3DRenderer;
class TerrainGenerator;
@@ -61,7 +61,7 @@ class _3D_EXPORT Map3D : public QObject
// 3D renderers
//
- QList renderers; //!< Stuff to render as 3D object
+ QList renderers; //!< Stuff to render as 3D object
bool skybox; //!< Whether to render skybox
QString skyboxFileBase;
diff --git a/src/3d/phongmaterialsettings.h b/src/3d/phongmaterialsettings.h
index c8722f1decd..42070de13fd 100644
--- a/src/3d/phongmaterialsettings.h
+++ b/src/3d/phongmaterialsettings.h
@@ -12,10 +12,10 @@ class _3D_EXPORT PhongMaterialSettings
{
public:
PhongMaterialSettings()
- : mAmbient( QColor::fromRgbF( 0.05f, 0.05f, 0.05f, 1.0f ) )
+ : mAmbient( QColor::fromRgbF( 0.1f, 0.1f, 0.1f, 1.0f ) )
, mDiffuse( QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) )
- , mSpecular( QColor::fromRgbF( 0.01f, 0.01f, 0.01f, 1.0f ) )
- , mShininess( 150.0f )
+ , mSpecular( QColor::fromRgbF( 1.0f, 1.0f, 1.0f, 1.0f ) )
+ , mShininess( 0.0f )
{
}
diff --git a/src/3d/scene.cpp b/src/3d/scene.cpp
index f009ac62d03..2e6da0b77cd 100644
--- a/src/3d/scene.cpp
+++ b/src/3d/scene.cpp
@@ -8,7 +8,7 @@
#include
#include "aabb.h"
-#include "abstract3drenderer.h"
+#include "qgsabstract3drenderer.h"
#include "cameracontroller.h"
#include "map3d.h"
#include "terrain.h"
@@ -59,12 +59,26 @@ Scene::Scene( const Map3D &map, Qt3DExtras::QForwardRenderer *defaultFrameGraph,
// create entities of renderers
- Q_FOREACH ( const Abstract3DRenderer *renderer, map.renderers )
+ Q_FOREACH ( const QgsAbstract3DRenderer *renderer, map.renderers )
{
Qt3DCore::QEntity *p = renderer->createEntity( map );
p->setParent( this );
}
+ // create entities of renderers of layers
+
+ Q_FOREACH ( QgsMapLayer *layer, map.layers() )
+ {
+ if ( layer->renderer3D() )
+ {
+ Qt3DCore::QEntity *p = layer->renderer3D()->createEntity( map );
+ p->setParent( this );
+ mLayerEntities.insert( layer, p );
+ }
+ connect( layer, &QgsMapLayer::renderer3DChanged, this, &Scene::onLayerRenderer3DChanged );
+ // TODO: connect( layer, &QgsMapLayer::willBeDeleted, this, &Scene::onLayerWillBeDeleted );
+ }
+
Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity;
Qt3DCore::QTransform *lightTransform = new Qt3DCore::QTransform;
lightTransform->setTranslation( QVector3D( 0, 1000, 0 ) );
@@ -83,10 +97,10 @@ Scene::Scene( const Map3D &map, Qt3DExtras::QForwardRenderer *defaultFrameGraph,
ChunkedEntity *testChunkEntity = new ChunkedEntity( AABB( -500, 0, -500, 500, 100, 500 ), 2.f, 3.f, 7, new TestChunkLoaderFactory );
testChunkEntity->setEnabled( false );
testChunkEntity->setParent( this );
- chunkEntities << testChunkEntity
+ chunkEntities << testChunkEntity;
#endif
- connect( mCameraController, &CameraController::cameraChanged, this, &Scene::onCameraChanged );
+ connect( mCameraController, &CameraController::cameraChanged, this, &Scene::onCameraChanged );
connect( mCameraController, &CameraController::viewportChanged, this, &Scene::onCameraChanged );
#if 0
@@ -190,3 +204,23 @@ void Scene::createTerrain()
onCameraChanged(); // force update of the new terrain
}
+
+void Scene::onLayerRenderer3DChanged()
+{
+ QgsMapLayer *layer = qobject_cast( sender() );
+ Q_ASSERT( layer );
+
+ // remove old entity - if any
+ Qt3DCore::QEntity *entity = mLayerEntities.take( layer );
+ if ( entity )
+ entity->deleteLater();
+
+ // add new entity - if any 3D renderer
+ QgsAbstract3DRenderer *renderer = layer->renderer3D();
+ if ( renderer )
+ {
+ Qt3DCore::QEntity *newEntity = renderer->createEntity( mMap );
+ newEntity->setParent( this );
+ mLayerEntities.insert( layer, newEntity );
+ }
+}
diff --git a/src/3d/scene.h b/src/3d/scene.h
index 7b617d3dd9e..0810abaa09c 100644
--- a/src/3d/scene.h
+++ b/src/3d/scene.h
@@ -21,6 +21,7 @@ namespace Qt3DExtras
class QForwardRenderer;
}
+class QgsMapLayer;
class CameraController;
class Map3D;
class Terrain;
@@ -42,6 +43,7 @@ class _3D_EXPORT Scene : public Qt3DCore::QEntity
void onCameraChanged();
void onFrameTriggered( float dt );
void createTerrain();
+ void onLayerRenderer3DChanged();
private:
const Map3D &mMap;
@@ -50,6 +52,8 @@ class _3D_EXPORT Scene : public Qt3DCore::QEntity
CameraController *mCameraController;
Terrain *mTerrain;
QList chunkEntities;
+ //! Keeps track of entities that belong to a particular layer
+ QMap mLayerEntities;
};
#endif // SCENE_H
diff --git a/src/3d/testapp/main.cpp b/src/3d/testapp/main.cpp
index 595c067925c..969bfaef846 100644
--- a/src/3d/testapp/main.cpp
+++ b/src/3d/testapp/main.cpp
@@ -5,10 +5,10 @@
#include
#include
-#include "abstract3drenderer.h"
#include "abstract3dsymbol.h"
#include "maptexturegenerator.h"
#include "sidepanel.h"
+#include "vectorlayer3drenderer.h"
#include "window3d.h"
#include "map3d.h"
#include "flatterraingenerator.h"
@@ -239,6 +239,7 @@ int main( int argc, char *argv[] )
hLayout->addWidget( container, 1 );
hLayout->addWidget( sidePanel );
+ widget.setWindowTitle( "QGIS 3D" );
widget.resize( 800, 600 );
widget.show();
diff --git a/src/3d/abstract3drenderer.cpp b/src/3d/vectorlayer3drenderer.cpp
similarity index 96%
rename from src/3d/abstract3drenderer.cpp
rename to src/3d/vectorlayer3drenderer.cpp
index 7f162aad325..a1989f7589d 100644
--- a/src/3d/abstract3drenderer.cpp
+++ b/src/3d/vectorlayer3drenderer.cpp
@@ -1,4 +1,4 @@
-#include "abstract3drenderer.h"
+#include "vectorlayer3drenderer.h"
#include "abstract3dsymbol.h"
#include "lineentity.h"
@@ -18,7 +18,7 @@ VectorLayer3DRenderer::~VectorLayer3DRenderer()
{
}
-Abstract3DRenderer *VectorLayer3DRenderer::clone() const
+VectorLayer3DRenderer *VectorLayer3DRenderer::clone() const
{
VectorLayer3DRenderer *r = new VectorLayer3DRenderer( mSymbol ? mSymbol->clone() : nullptr );
r->layerRef = layerRef;
diff --git a/src/3d/abstract3drenderer.h b/src/3d/vectorlayer3drenderer.h
similarity index 57%
rename from src/3d/abstract3drenderer.h
rename to src/3d/vectorlayer3drenderer.h
index 0b7cc2bf6b9..2537579ca2a 100644
--- a/src/3d/abstract3drenderer.h
+++ b/src/3d/vectorlayer3drenderer.h
@@ -1,8 +1,10 @@
-#ifndef ABSTRACT3DRENDERER_H
-#define ABSTRACT3DRENDERER_H
+#ifndef VECTORLAYER3DRENDERER_H
+#define VECTORLAYER3DRENDERER_H
#include "qgis_3d.h"
+#include "qgsabstract3drenderer.h"
+
#include "phongmaterialsettings.h"
#include "utils.h"
@@ -13,34 +15,11 @@
class QgsVectorLayer;
class Abstract3DSymbol;
-class Map3D;
-
-
-namespace Qt3DCore
-{
- class QEntity;
-}
-
-class _3D_EXPORT Abstract3DRenderer //: public QObject
-{
- //Q_OBJECT
- public:
- virtual ~Abstract3DRenderer() {}
-
- virtual QString type() const = 0;
- virtual Abstract3DRenderer *clone() const = 0;
- virtual Qt3DCore::QEntity *createEntity( const Map3D &map ) const = 0;
-
- virtual void writeXml( QDomElement &elem ) const = 0;
- virtual void readXml( const QDomElement &elem ) = 0;
- virtual void resolveReferences( const QgsProject &project ) { Q_UNUSED( project ); }
-};
-
/** 3D renderer that renders all features of a vector layer with the same 3D symbol.
- * The appearance if completely defined by the symbol.
+ * The appearance is completely defined by the symbol.
*/
-class _3D_EXPORT VectorLayer3DRenderer : public Abstract3DRenderer
+class _3D_EXPORT VectorLayer3DRenderer : public QgsAbstract3DRenderer
{
public:
//! Takes ownership of the symbol object
@@ -55,7 +34,7 @@ class _3D_EXPORT VectorLayer3DRenderer : public Abstract3DRenderer
const Abstract3DSymbol *symbol() const;
QString type() const override { return "vector"; }
- Abstract3DRenderer *clone() const override;
+ VectorLayer3DRenderer *clone() const override;
Qt3DCore::QEntity *createEntity( const Map3D &map ) const override;
void writeXml( QDomElement &elem ) const override;
@@ -68,4 +47,4 @@ class _3D_EXPORT VectorLayer3DRenderer : public Abstract3DRenderer
};
-#endif // ABSTRACT3DRENDERER_H
+#endif // VECTORLAYER3DRENDERER_H
diff --git a/src/app/3d/qgsphongmaterialwidget.cpp b/src/app/3d/qgsphongmaterialwidget.cpp
new file mode 100644
index 00000000000..a884aa99a5f
--- /dev/null
+++ b/src/app/3d/qgsphongmaterialwidget.cpp
@@ -0,0 +1,35 @@
+#include "qgsphongmaterialwidget.h"
+
+#include "phongmaterialsettings.h"
+
+
+QgsPhongMaterialWidget::QgsPhongMaterialWidget( QWidget *parent )
+ : QWidget( parent )
+{
+ setupUi( this );
+
+ setMaterial( PhongMaterialSettings() );
+
+ connect( btnDiffuse, &QgsColorButton::colorChanged, this, &QgsPhongMaterialWidget::changed );
+ connect( btnAmbient, &QgsColorButton::colorChanged, this, &QgsPhongMaterialWidget::changed );
+ connect( btnSpecular, &QgsColorButton::colorChanged, this, &QgsPhongMaterialWidget::changed );
+ connect( spinShininess, static_cast( &QDoubleSpinBox::valueChanged ), this, &QgsPhongMaterialWidget::changed );
+}
+
+void QgsPhongMaterialWidget::setMaterial( const PhongMaterialSettings &material )
+{
+ btnDiffuse->setColor( material.diffuse() );
+ btnAmbient->setColor( material.ambient() );
+ btnSpecular->setColor( material.specular() );
+ spinShininess->setValue( material.shininess() );
+}
+
+PhongMaterialSettings QgsPhongMaterialWidget::material() const
+{
+ PhongMaterialSettings m;
+ m.setDiffuse( btnDiffuse->color() );
+ m.setAmbient( btnAmbient->color() );
+ m.setSpecular( btnSpecular->color() );
+ m.setShininess( spinShininess->value() );
+ return m;
+}
diff --git a/src/app/3d/qgsphongmaterialwidget.h b/src/app/3d/qgsphongmaterialwidget.h
new file mode 100644
index 00000000000..dc0acc742ad
--- /dev/null
+++ b/src/app/3d/qgsphongmaterialwidget.h
@@ -0,0 +1,27 @@
+#ifndef QGSPHONGMATERIALWIDGET_H
+#define QGSPHONGMATERIALWIDGET_H
+
+#include
+
+#include
+
+class PhongMaterialSettings;
+
+
+//! Widget for configuration of Phong material settings
+class QgsPhongMaterialWidget : public QWidget, private Ui::PhongMaterialWidget
+{
+ Q_OBJECT
+ public:
+ explicit QgsPhongMaterialWidget( QWidget *parent = nullptr );
+
+ void setMaterial( const PhongMaterialSettings &material );
+ PhongMaterialSettings material() const;
+
+ signals:
+ void changed();
+
+ public slots:
+};
+
+#endif // QGSPHONGMATERIALWIDGET_H
diff --git a/src/app/3d/qgspolygon3dsymbolwidget.cpp b/src/app/3d/qgspolygon3dsymbolwidget.cpp
new file mode 100644
index 00000000000..2335234fac4
--- /dev/null
+++ b/src/app/3d/qgspolygon3dsymbolwidget.cpp
@@ -0,0 +1,38 @@
+#include "qgspolygon3dsymbolwidget.h"
+
+#include "abstract3dsymbol.h"
+
+
+QgsPolygon3DSymbolWidget::QgsPolygon3DSymbolWidget( QWidget *parent )
+ : QWidget( parent )
+{
+ setupUi( this );
+
+ setSymbol( Polygon3DSymbol() );
+
+ connect( spinHeight, static_cast( &QDoubleSpinBox::valueChanged ), this, &QgsPolygon3DSymbolWidget::changed );
+ connect( spinExtrusion, static_cast( &QDoubleSpinBox::valueChanged ), this, &QgsPolygon3DSymbolWidget::changed );
+ connect( cboAltClamping, static_cast( &QComboBox::currentIndexChanged ), this, &QgsPolygon3DSymbolWidget::changed );
+ connect( cboAltBinding, static_cast( &QComboBox::currentIndexChanged ), this, &QgsPolygon3DSymbolWidget::changed );
+ connect( widgetMaterial, &QgsPhongMaterialWidget::changed, this, &QgsPolygon3DSymbolWidget::changed );
+}
+
+void QgsPolygon3DSymbolWidget::setSymbol( const Polygon3DSymbol &symbol )
+{
+ spinHeight->setValue( symbol.height );
+ spinExtrusion->setValue( symbol.extrusionHeight );
+ cboAltClamping->setCurrentIndex( ( int ) symbol.altClamping );
+ cboAltBinding->setCurrentIndex( ( int ) symbol.altBinding );
+ widgetMaterial->setMaterial( symbol.material );
+}
+
+Polygon3DSymbol QgsPolygon3DSymbolWidget::symbol() const
+{
+ Polygon3DSymbol sym;
+ sym.height = spinHeight->value();
+ sym.extrusionHeight = spinExtrusion->value();
+ sym.altClamping = ( AltitudeClamping ) cboAltClamping->currentIndex();
+ sym.altBinding = ( AltitudeBinding ) cboAltBinding->currentIndex();
+ sym.material = widgetMaterial->material();
+ return sym;
+}
diff --git a/src/app/3d/qgspolygon3dsymbolwidget.h b/src/app/3d/qgspolygon3dsymbolwidget.h
new file mode 100644
index 00000000000..ec71a28a1d9
--- /dev/null
+++ b/src/app/3d/qgspolygon3dsymbolwidget.h
@@ -0,0 +1,26 @@
+#ifndef QGSPOLYGON3DSYMBOLWIDGET_H
+#define QGSPOLYGON3DSYMBOLWIDGET_H
+
+#include
+
+#include "ui_polygon3dsymbolwidget.h"
+
+class Polygon3DSymbol;
+
+//! A widget for configuration of 3D symbol for polygons
+class QgsPolygon3DSymbolWidget : public QWidget, private Ui::Polygon3DSymbolWidget
+{
+ Q_OBJECT
+ public:
+ explicit QgsPolygon3DSymbolWidget( QWidget *parent = nullptr );
+
+ void setSymbol( const Polygon3DSymbol &symbol );
+ Polygon3DSymbol symbol() const;
+
+ signals:
+ void changed();
+
+ public slots:
+};
+
+#endif // QGSPOLYGON3DSYMBOLWIDGET_H
diff --git a/src/app/3d/qgsvectorlayer3drendererwidget.cpp b/src/app/3d/qgsvectorlayer3drendererwidget.cpp
new file mode 100644
index 00000000000..071023b7865
--- /dev/null
+++ b/src/app/3d/qgsvectorlayer3drendererwidget.cpp
@@ -0,0 +1,88 @@
+#include "qgsvectorlayer3drendererwidget.h"
+
+#include "abstract3dsymbol.h"
+#include "qgspolygon3dsymbolwidget.h"
+#include "vectorlayer3drenderer.h"
+
+#include "qgsvectorlayer.h"
+
+#include
+#include
+
+QgsVectorLayer3DRendererWidget::QgsVectorLayer3DRendererWidget( QgsVectorLayer *layer, QgsMapCanvas *canvas, QWidget *parent )
+ : QgsMapLayerConfigWidget( layer, canvas, parent )
+{
+ setPanelTitle( tr( "3D View" ) );
+
+ QVBoxLayout *layout = new QVBoxLayout( this );
+ chkEnabled = new QCheckBox( "Enable 3D renderer", this );
+ widgetPolygon = new QgsPolygon3DSymbolWidget( this );
+ layout->addWidget( chkEnabled );
+ layout->addWidget( widgetPolygon );
+
+ widgetPolygon->setEnabled( false );
+
+ connect( chkEnabled, &QCheckBox::clicked, this, &QgsVectorLayer3DRendererWidget::onEnabledClicked );
+ connect( widgetPolygon, &QgsPolygon3DSymbolWidget::changed, this, &QgsVectorLayer3DRendererWidget::widgetChanged );
+}
+
+QgsVectorLayer3DRendererWidget::~QgsVectorLayer3DRendererWidget()
+{
+}
+
+void QgsVectorLayer3DRendererWidget::setLayer( QgsVectorLayer *layer )
+{
+ mLayer = layer;
+
+ QgsAbstract3DRenderer *r = layer->renderer3D();
+ if ( r && r->type() == "vector" )
+ {
+ VectorLayer3DRenderer *vectorRenderer = static_cast( r );
+ setRenderer( vectorRenderer );
+ }
+ else
+ {
+ setRenderer( nullptr );
+ }
+}
+
+void QgsVectorLayer3DRendererWidget::setRenderer( const VectorLayer3DRenderer *renderer )
+{
+ mRenderer.reset( renderer ? renderer->clone() : nullptr );
+
+ whileBlocking( chkEnabled )->setChecked( ( bool )mRenderer );
+ widgetPolygon->setEnabled( chkEnabled->isChecked() );
+
+ if ( mRenderer && mRenderer->symbol() && mRenderer->symbol()->type() == "polygon" )
+ {
+ whileBlocking( widgetPolygon )->setSymbol( *static_cast( mRenderer->symbol() ) );
+ }
+}
+
+VectorLayer3DRenderer *QgsVectorLayer3DRendererWidget::renderer()
+{
+ if ( chkEnabled->isChecked() )
+ {
+ VectorLayer3DRenderer *r = new VectorLayer3DRenderer( new Polygon3DSymbol( widgetPolygon->symbol() ) );
+ r->setLayer( qobject_cast( mLayer ) );
+ mRenderer.reset( r );
+ }
+ else
+ {
+ mRenderer.reset();
+ }
+
+ return mRenderer.get();
+}
+
+void QgsVectorLayer3DRendererWidget::apply()
+{
+ VectorLayer3DRenderer *r = renderer();
+ mLayer->setRenderer3D( r ? r->clone() : nullptr );
+}
+
+void QgsVectorLayer3DRendererWidget::onEnabledClicked()
+{
+ widgetPolygon->setEnabled( chkEnabled->isChecked() );
+ emit widgetChanged();
+}
diff --git a/src/app/3d/qgsvectorlayer3drendererwidget.h b/src/app/3d/qgsvectorlayer3drendererwidget.h
new file mode 100644
index 00000000000..07703c1e165
--- /dev/null
+++ b/src/app/3d/qgsvectorlayer3drendererwidget.h
@@ -0,0 +1,43 @@
+#ifndef QGSVECTORLAYER3DRENDERERWIDGET_H
+#define QGSVECTORLAYER3DRENDERERWIDGET_H
+
+#include
+
+#include "qgsmaplayerconfigwidget.h"
+
+class QCheckBox;
+class QgsPolygon3DSymbolWidget;
+class QgsVectorLayer;
+class QgsMapCanvas;
+class VectorLayer3DRenderer;
+
+
+//! Widget for configuration of 3D renderer of a vector layer
+class QgsVectorLayer3DRendererWidget : public QgsMapLayerConfigWidget
+{
+ Q_OBJECT
+ public:
+ explicit QgsVectorLayer3DRendererWidget( QgsVectorLayer *layer, QgsMapCanvas *canvas, QWidget *parent = nullptr );
+ ~QgsVectorLayer3DRendererWidget();
+
+ void setLayer( QgsVectorLayer *layer );
+
+ //! no transfer of ownership
+ void setRenderer( const VectorLayer3DRenderer *renderer );
+ //! no transfer of ownership
+ VectorLayer3DRenderer *renderer();
+
+ public slots:
+ virtual void apply() override;
+
+ private slots:
+ void onEnabledClicked();
+
+ private:
+ QCheckBox *chkEnabled;
+ QgsPolygon3DSymbolWidget *widgetPolygon;
+
+ std::unique_ptr mRenderer;
+};
+
+#endif // QGSVECTORLAYER3DRENDERERWIDGET_H
diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt
index 33ca7904a24..18ee7ee17e7 100755
--- a/src/app/CMakeLists.txt
+++ b/src/app/CMakeLists.txt
@@ -370,6 +370,9 @@ IF (WITH_3D)
3d/qgs3dmapcanvas.cpp
3d/qgs3dmapcanvasdockwidget.cpp
3d/qgs3dmapconfigwidget.cpp
+ 3d/qgspolygon3dsymbolwidget.cpp
+ 3d/qgsphongmaterialwidget.cpp
+ 3d/qgsvectorlayer3drendererwidget.cpp
)
SET (QGIS_APP_MOC_HDRS
@@ -377,6 +380,9 @@ IF (WITH_3D)
3d/qgs3dmapcanvas.h
3d/qgs3dmapcanvasdockwidget.h
3d/qgs3dmapconfigwidget.h
+ 3d/qgspolygon3dsymbolwidget.h
+ 3d/qgsphongmaterialwidget.h
+ 3d/qgsvectorlayer3drendererwidget.h
)
ENDIF (WITH_3D)
@@ -561,6 +567,7 @@ INCLUDE_DIRECTORIES(
IF (WITH_3D)
INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/src/app/3d
+ ${CMAKE_SOURCE_DIR}/src/core/3d
${CMAKE_SOURCE_DIR}/src/3d
${CMAKE_SOURCE_DIR}/src/3d/terrain
${CMAKE_SOURCE_DIR}/src/3d/chunks
diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp
index 8601726717c..6b4a75f5d53 100644
--- a/src/app/qgisapp.cpp
+++ b/src/app/qgisapp.cpp
@@ -9879,6 +9879,7 @@ void QgisApp::newMapCanvas()
}
}
+#include "qgsabstract3drenderer.h"
#include "qgs3dmapcanvasdockwidget.h"
#include "map3d.h"
#include "flatterraingenerator.h"
@@ -9890,8 +9891,6 @@ void QgisApp::new3DMapCanvas()
QgsRectangle fullExtent = mMapCanvas->fullExtent();
Map3D *map = new Map3D;
- map->setShowTerrainBoundingBoxes( true );
- map->setShowTerrainTilesInfo( true );
map->crs = prj->crs();
map->originX = fullExtent.center().x();
map->originY = fullExtent.center().y();
@@ -9910,7 +9909,7 @@ void QgisApp::new3DMapCanvas()
map3DWidget->setGeometry( QRect( rect().width() * 0.75, rect().height() * 0.5, 400, 400 ) );
map3DWidget->setMap( map );
map3DWidget->setMainCanvas( mMapCanvas );
- addDockWidget( Qt::RightDockWidgetArea, map3DWidget );
+ addDockWidget( Qt::BottomDockWidgetArea, map3DWidget );
}
void QgisApp::setExtent( const QgsRectangle &rect )
diff --git a/src/app/qgslayerstylingwidget.cpp b/src/app/qgslayerstylingwidget.cpp
index ecdaca3c615..4774fc8eb78 100644
--- a/src/app/qgslayerstylingwidget.cpp
+++ b/src/app/qgslayerstylingwidget.cpp
@@ -45,6 +45,10 @@
#include "qgsruntimeprofiler.h"
#include "qgsrasterminmaxwidget.h"
+#ifdef HAVE_3D
+#include "qgsvectorlayer3drendererwidget.h"
+#endif
+
QgsLayerStylingWidget::QgsLayerStylingWidget( QgsMapCanvas *canvas, const QList &pages, QWidget *parent )
: QWidget( parent )
@@ -158,6 +162,13 @@ void QgsLayerStylingWidget::setLayer( QgsMapLayer *layer )
labelItem->setData( Qt::UserRole, VectorLabeling );
labelItem->setToolTip( tr( "Labels" ) );
mOptionsListWidget->addItem( labelItem );
+
+#ifdef HAVE_3D
+ QListWidgetItem *symbol3DItem = new QListWidgetItem( QgsApplication::getThemeIcon( QStringLiteral( "3d.svg" ) ), QString() );
+ symbol3DItem->setData( Qt::UserRole, Symbology3D );
+ symbol3DItem->setToolTip( tr( "3D View" ) );
+ mOptionsListWidget->addItem( symbol3DItem );
+#endif
}
else if ( layer->type() == QgsMapLayer::RasterLayer )
{
@@ -318,6 +329,12 @@ void QgsLayerStylingWidget::updateCurrentWidgetLayer()
{
mRasterStyleWidget = widget;
}
+#ifdef HAVE_3D
+ else if ( QgsVectorLayer3DRendererWidget *widget = qobject_cast( current ) )
+ {
+ mVector3DWidget = widget;
+ }
+#endif
}
@@ -369,6 +386,20 @@ void QgsLayerStylingWidget::updateCurrentWidgetLayer()
mWidgetStack->setMainPanel( mLabelingWidget );
break;
}
+#ifdef HAVE_3D
+ case 2: // 3D View
+ {
+ if ( !mVector3DWidget )
+ {
+ mVector3DWidget = new QgsVectorLayer3DRendererWidget( nullptr, mMapCanvas, mWidgetStack );
+ mVector3DWidget->setDockMode( true );
+ connect( mVector3DWidget, &QgsVectorLayer3DRendererWidget::widgetChanged, this, &QgsLayerStylingWidget::autoApply );
+ }
+ mVector3DWidget->setLayer( vlayer );
+ mWidgetStack->setMainPanel( mVector3DWidget );
+ break;
+ }
+#endif
default:
break;
}
diff --git a/src/app/qgslayerstylingwidget.h b/src/app/qgslayerstylingwidget.h
index 977a9378502..c37f7d08704 100644
--- a/src/app/qgslayerstylingwidget.h
+++ b/src/app/qgslayerstylingwidget.h
@@ -39,6 +39,7 @@ class QgsRendererRasterPropertiesWidget;
class QgsUndoWidget;
class QgsRasterHistogramWidget;
class QgsMapLayerStyleManagerWidget;
+class QgsVectorLayer3DRendererWidget;
class APP_EXPORT QgsLayerStyleManagerWidgetFactory : public QgsMapLayerConfigWidgetFactory
{
@@ -84,6 +85,7 @@ class APP_EXPORT QgsLayerStylingWidget : public QWidget, private Ui::QgsLayerSty
RasterTransparency,
RasterHistogram,
History,
+ Symbology3D,
};
QgsLayerStylingWidget( QgsMapCanvas *canvas, const QList &pages, QWidget *parent = 0 );
@@ -131,6 +133,9 @@ class APP_EXPORT QgsLayerStylingWidget : public QWidget, private Ui::QgsLayerSty
QgsUndoWidget *mUndoWidget = nullptr;
QgsMapLayer *mCurrentLayer = nullptr;
QgsLabelingWidget *mLabelingWidget = nullptr;
+#ifdef HAVE_3D
+ QgsVectorLayer3DRendererWidget *mVector3DWidget = nullptr;
+#endif
QgsRendererRasterPropertiesWidget *mRasterStyleWidget = nullptr;
QList mPageFactories;
QMap mUserPages;
diff --git a/src/core/3d/qgs3drendererregistry.cpp b/src/core/3d/qgs3drendererregistry.cpp
new file mode 100644
index 00000000000..355a0df146f
--- /dev/null
+++ b/src/core/3d/qgs3drendererregistry.cpp
@@ -0,0 +1,45 @@
+#include "qgs3drendererregistry.h"
+
+
+Qgs3DRendererAbstractMetadata::Qgs3DRendererAbstractMetadata( const QString &name )
+ : mName( name )
+{
+}
+
+QString Qgs3DRendererAbstractMetadata::name() const
+{
+ return mName;
+}
+
+
+// ----------
+
+
+Qgs3DRendererRegistry::Qgs3DRendererRegistry()
+{
+}
+
+Qgs3DRendererRegistry::~Qgs3DRendererRegistry()
+{
+ qDeleteAll( mRenderers );
+}
+
+void Qgs3DRendererRegistry::addRenderer( Qgs3DRendererAbstractMetadata *metadata )
+{
+ mRenderers.insert( metadata->name(), metadata );
+}
+
+void Qgs3DRendererRegistry::removeRenderer( const QString &name )
+{
+ delete mRenderers.take( name );
+}
+
+Qgs3DRendererAbstractMetadata *Qgs3DRendererRegistry::rendererMetadata( const QString &name ) const
+{
+ return mRenderers.value( name );
+}
+
+QStringList Qgs3DRendererRegistry::renderersList() const
+{
+ return mRenderers.keys();
+}
diff --git a/src/core/3d/qgs3drendererregistry.h b/src/core/3d/qgs3drendererregistry.h
new file mode 100644
index 00000000000..03eaf1efb79
--- /dev/null
+++ b/src/core/3d/qgs3drendererregistry.h
@@ -0,0 +1,61 @@
+#ifndef QGS3DRENDERERREGISTRY_H
+#define QGS3DRENDERERREGISTRY_H
+
+#include "qgis_core.h"
+
+#include
+
+class QDomElement;
+class QgsAbstract3DRenderer;
+class QgsReadWriteContext;
+
+
+/**
+ * Base metadata class for 3D renderers. Instances of derived classes may be registered in Qgs3DRendererRegistry.
+ * \since QGIS 3.0
+ * \ingroup core
+ */
+class CORE_EXPORT Qgs3DRendererAbstractMetadata
+{
+ public:
+
+ Qgs3DRendererAbstractMetadata( const QString &name );
+
+ QString name() const;
+
+ /** Return new instance of the renderer given the DOM element. Returns NULL on error.
+ * Pure virtual function: must be implemented in derived classes. */
+ virtual QgsAbstract3DRenderer *createRenderer( QDomElement &elem, const QgsReadWriteContext &context ) = 0;
+
+ protected:
+ //! name used within QGIS for identification (the same what renderer's type() returns)
+ QString mName;
+};
+
+
+/**
+ * Keeps track of available 3D renderers. Should be accessed through QgsApplication::renderer3DRegistry() singleton.
+ * \since QGIS 3.0
+ * \ingroup core
+ */
+class CORE_EXPORT Qgs3DRendererRegistry
+{
+ public:
+ Qgs3DRendererRegistry();
+
+ ~Qgs3DRendererRegistry();
+
+ //! takes ownership
+ void addRenderer( Qgs3DRendererAbstractMetadata *metadata );
+
+ void removeRenderer( const QString &name );
+
+ Qgs3DRendererAbstractMetadata *rendererMetadata( const QString &name ) const;
+
+ QStringList renderersList() const;
+
+ private:
+ QMap mRenderers;
+};
+
+#endif // QGS3DRENDERERREGISTRY_H
diff --git a/src/core/3d/qgsabstract3drenderer.cpp b/src/core/3d/qgsabstract3drenderer.cpp
new file mode 100644
index 00000000000..a91a13ec801
--- /dev/null
+++ b/src/core/3d/qgsabstract3drenderer.cpp
@@ -0,0 +1,11 @@
+#include "qgsabstract3drenderer.h"
+
+
+QgsAbstract3DRenderer::~QgsAbstract3DRenderer()
+{
+}
+
+void QgsAbstract3DRenderer::resolveReferences( const QgsProject &project )
+{
+ Q_UNUSED( project );
+}
diff --git a/src/core/3d/qgsabstract3drenderer.h b/src/core/3d/qgsabstract3drenderer.h
new file mode 100644
index 00000000000..14d2044d0c9
--- /dev/null
+++ b/src/core/3d/qgsabstract3drenderer.h
@@ -0,0 +1,35 @@
+#ifndef QGSABSTRACT3DRENDERER_H
+#define QGSABSTRACT3DRENDERER_H
+
+#include "qgis_core.h"
+
+#include
+
+class QDomElement;
+class QgsProject;
+class Map3D;
+
+namespace Qt3DCore
+{
+ class QEntity;
+}
+
+//! Base class for all renderers that may to participate in 3D view.
+class CORE_EXPORT QgsAbstract3DRenderer //: public QObject
+{
+ //Q_OBJECT
+ public:
+ virtual ~QgsAbstract3DRenderer();
+
+ virtual QString type() const = 0;
+ virtual QgsAbstract3DRenderer *clone() const = 0;
+ virtual Qt3DCore::QEntity *createEntity( const Map3D &map ) const = 0;
+
+ virtual void writeXml( QDomElement &elem ) const = 0;
+ virtual void readXml( const QDomElement &elem ) = 0;
+ virtual void resolveReferences( const QgsProject &project );
+};
+
+
+
+#endif // QGSABSTRACT3DRENDERER_H
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 7bbe7b18f02..160addce4dd 100755
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -463,6 +463,9 @@ SET(QGIS_CORE_SRCS
geometry/qgswkbptr.cpp
geometry/qgswkbtypes.cpp
+ 3d/qgs3drendererregistry.cpp
+ 3d/qgsabstract3drenderer.cpp
+
fieldformatter/qgsdatetimefieldformatter.cpp
fieldformatter/qgsfallbackfieldformatter.cpp
fieldformatter/qgskeyvaluefieldformatter.cpp
@@ -1093,6 +1096,9 @@ SET(QGIS_CORE_HDRS
geometry/qgswkbptr.h
geometry/qgswkbtypes.h
+ 3d/qgs3drendererregistry.h
+ 3d/qgsabstract3drenderer.h
+
fieldformatter/qgsdatetimefieldformatter.h
fieldformatter/qgsfallbackfieldformatter.h
fieldformatter/qgskeyvaluefieldformatter.h
@@ -1118,6 +1124,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${LIBZIP_INCLUDE_DIR}
+ 3d
annotations
auth
composer
diff --git a/src/core/qgsapplication.cpp b/src/core/qgsapplication.cpp
index 13d14d9d0b6..4448fce17ef 100644
--- a/src/core/qgsapplication.cpp
+++ b/src/core/qgsapplication.cpp
@@ -42,6 +42,7 @@
#include "qgsuserprofile.h"
#include "qgsuserprofilemanager.h"
#include "qgsreferencedgeometry.h"
+#include "qgs3drendererregistry.h"
#include "gps/qgsgpsconnectionregistry.h"
#include "processing/qgsprocessingregistry.h"
@@ -1574,6 +1575,11 @@ QgsFieldFormatterRegistry *QgsApplication::fieldFormatterRegistry()
return members()->mFieldFormatterRegistry;
}
+Qgs3DRendererRegistry *QgsApplication::renderer3DRegistry()
+{
+ return members()->m3DRendererRegistry;
+}
+
QgsApplication::ApplicationMembers::ApplicationMembers()
{
// don't use initializer lists or scoped pointers - as more objects are added here we
@@ -1598,11 +1604,13 @@ QgsApplication::ApplicationMembers::ApplicationMembers()
mLayoutItemRegistry->populate();
mProcessingRegistry->addProvider( new QgsNativeAlgorithms( mProcessingRegistry ) );
mAnnotationRegistry = new QgsAnnotationRegistry();
+ m3DRendererRegistry = new Qgs3DRendererRegistry();
}
QgsApplication::ApplicationMembers::~ApplicationMembers()
{
delete mActionScopeRegistry;
+ delete m3DRendererRegistry;
delete mAnnotationRegistry;
delete mColorSchemeRegistry;
delete mFieldFormatterRegistry;
diff --git a/src/core/qgsapplication.h b/src/core/qgsapplication.h
index b51e0469e44..5b935c88f38 100644
--- a/src/core/qgsapplication.h
+++ b/src/core/qgsapplication.h
@@ -23,6 +23,7 @@
#include "qgis.h"
#include "qgsconfig.h"
+class Qgs3DRendererRegistry;
class QgsActionScopeRegistry;
class QgsRuntimeProfiler;
class QgsTaskManager;
@@ -583,6 +584,13 @@ class CORE_EXPORT QgsApplication : public QApplication
*/
static QgsFieldFormatterRegistry *fieldFormatterRegistry();
+ /**
+ * Returns registry of available 3D renderers.
+ * \note not available in Python bindings
+ * \since QGIS 3.0
+ */
+ static Qgs3DRendererRegistry *renderer3DRegistry() SIP_SKIP;
+
/**
* This string is used to represent the value `NULL` throughout QGIS.
*
@@ -698,6 +706,7 @@ class CORE_EXPORT QgsApplication : public QApplication
struct ApplicationMembers
{
+ Qgs3DRendererRegistry *m3DRendererRegistry = nullptr;
QgsActionScopeRegistry *mActionScopeRegistry = nullptr;
QgsAnnotationRegistry *mAnnotationRegistry = nullptr;
QgsColorSchemeRegistry *mColorSchemeRegistry = nullptr;
diff --git a/src/core/qgsmaplayer.cpp b/src/core/qgsmaplayer.cpp
index 18544bb1f34..830f0e7a623 100644
--- a/src/core/qgsmaplayer.cpp
+++ b/src/core/qgsmaplayer.cpp
@@ -28,6 +28,7 @@
#include
+#include "qgsabstract3drenderer.h"
#include "qgsapplication.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsdatasourceuri.h"
@@ -88,6 +89,7 @@ QgsMapLayer::QgsMapLayer( QgsMapLayer::LayerType type,
QgsMapLayer::~QgsMapLayer()
{
+ delete m3DRenderer;
delete mLegend;
delete mStyleManager;
}
@@ -1673,6 +1675,21 @@ QgsMapLayerStyleManager *QgsMapLayer::styleManager() const
return mStyleManager;
}
+void QgsMapLayer::setRenderer3D( QgsAbstract3DRenderer *renderer )
+{
+ if ( renderer == m3DRenderer )
+ return;
+
+ delete m3DRenderer;
+ m3DRenderer = renderer;
+ emit renderer3DChanged();
+}
+
+QgsAbstract3DRenderer *QgsMapLayer::renderer3D() const
+{
+ return m3DRenderer;
+}
+
void QgsMapLayer::triggerRepaint( bool deferredUpdate )
{
emit repaintRequested( deferredUpdate );
diff --git a/src/core/qgsmaplayer.h b/src/core/qgsmaplayer.h
index d2e5f1f10a9..0635263272c 100644
--- a/src/core/qgsmaplayer.h
+++ b/src/core/qgsmaplayer.h
@@ -36,6 +36,7 @@
#include "qgsmaplayerdependency.h"
#include "qgslayermetadata.h"
+class QgsAbstract3DRenderer;
class QgsDataProvider;
class QgsMapLayerLegend;
class QgsMapLayerRenderer;
@@ -675,6 +676,20 @@ class CORE_EXPORT QgsMapLayer : public QObject
*/
QgsMapLayerStyleManager *styleManager() const;
+ /**
+ * Sets 3D renderer for the layer. Takes ownership of the renderer.
+ * \note not available in Python bindings
+ * \since QGIS 3.0
+ */
+ void setRenderer3D( QgsAbstract3DRenderer *renderer SIP_TRANSFER ) SIP_SKIP;
+
+ /**
+ * Returns 3D renderer associated with the layer. May be null.
+ * \note not available in Python bindings
+ * \since QGIS 3.0
+ */
+ QgsAbstract3DRenderer *renderer3D() const SIP_SKIP;
+
/** Tests whether the layer should be visible at the specified \a scale.
* The \a scale value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map.
* \returns true if the layer is visible at the given scale.
@@ -897,6 +912,12 @@ class CORE_EXPORT QgsMapLayer : public QObject
*/
void legendChanged();
+ /**
+ * Signal emitted when 3D renderer associated with the layer has changed.
+ * \since QGIS 3.0
+ */
+ void renderer3DChanged();
+
/**
* Emitted whenever the configuration is changed. The project listens to this signal
* to be marked as dirty.
@@ -1080,6 +1101,9 @@ class CORE_EXPORT QgsMapLayer : public QObject
QgsLayerMetadata mMetadata;
+ //! Renderer for 3D views
+ QgsAbstract3DRenderer *m3DRenderer = nullptr;
+
};
Q_DECLARE_METATYPE( QgsMapLayer * )
diff --git a/src/ui/3d/phongmaterialwidget.ui b/src/ui/3d/phongmaterialwidget.ui
new file mode 100644
index 00000000000..a4aedb45e83
--- /dev/null
+++ b/src/ui/3d/phongmaterialwidget.ui
@@ -0,0 +1,94 @@
+
+
+ PhongMaterialWidget
+
+
+
+ 0
+ 0
+ 334
+ 252
+
+
+
+ Form
+
+
+ -
+
+
+ Diffuse
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ Ambient
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ Specular
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ Shininess
+
+
+
+ -
+
+
+ 1000.000000000000000
+
+
+
+
+
+
+
+ QgsColorButton
+ QToolButton
+
+ 1
+
+
+
+
+
diff --git a/src/ui/3d/polygon3dsymbolwidget.ui b/src/ui/3d/polygon3dsymbolwidget.ui
new file mode 100644
index 00000000000..d638e98eaa8
--- /dev/null
+++ b/src/ui/3d/polygon3dsymbolwidget.ui
@@ -0,0 +1,110 @@
+
+
+ Polygon3DSymbolWidget
+
+
+
+ 0
+ 0
+ 538
+ 452
+
+
+
+ Form
+
+
+ -
+
+
-
+
+
+ Height
+
+
+
+ -
+
+
+ -
+
+
+ Extrusion
+
+
+
+ -
+
+
+ -
+
+
+ Altitude Clamping
+
+
+
+ -
+
+
-
+
+ Absolute
+
+
+ -
+
+ Relative
+
+
+ -
+
+ Terrain
+
+
+
+
+ -
+
+
+ Altitude Binding
+
+
+
+ -
+
+
-
+
+ Vertex
+
+
+ -
+
+ Centroid
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+
+
+
+ QgsPhongMaterialWidget
+ QWidget
+
+ 1
+
+
+
+
+
diff --git a/src/ui/symbollayer/widget_simplefill.ui b/src/ui/symbollayer/widget_simplefill.ui
index e964bfbbc0c..9a19506acbe 100644
--- a/src/ui/symbollayer/widget_simplefill.ui
+++ b/src/ui/symbollayer/widget_simplefill.ui
@@ -6,8 +6,8 @@
0
0
- 332
- 319
+ 573
+ 507
@@ -336,6 +336,12 @@
+
+ QgsColorButton
+ QToolButton
+
+ 1
+
QgsPropertyOverrideButton
QToolButton
@@ -352,12 +358,6 @@
1
-
- QgsColorButton
- QToolButton
-
- 1
-
QgsPenJoinStyleComboBox
QComboBox