Skip to content
Permalink
Browse files

GUI for configuration of 3D polygon symbols for vector layers

In the style dock there is a new "3D View" tab - so far working just for polygon layers.
It is possible to select a polygon layer, enable 3D renderer and adjust its properties.
If a 3D Map View is open, it will be immediately updated (if auto-apply is enabled)

Very exciting! :-)
  • Loading branch information
wonder-sk committed Jul 26, 2017
1 parent b9dd6bc commit ba7573a94ef615526705d61155cb8c89bed462fb
Showing with 850 additions and 60 deletions.
  1. +1 −0 CMakeLists.txt
  2. +3 −1 cmake_templates/qgsconfig.h.in
  3. +1 −0 images/images.qrc
  4. +38 −0 images/themes/default/3d.svg
  5. +1 −0 python/core/qgsapplication.sip
  6. +8 −0 python/core/qgsmaplayer.sip
  7. +3 −2 src/3d/CMakeLists.txt
  8. +5 −5 src/3d/map3d.cpp
  9. +2 −2 src/3d/map3d.h
  10. +3 −3 src/3d/phongmaterialsettings.h
  11. +38 −4 src/3d/scene.cpp
  12. +4 −0 src/3d/scene.h
  13. +2 −1 src/3d/testapp/main.cpp
  14. +2 −2 src/3d/{abstract3drenderer.cpp → vectorlayer3drenderer.cpp}
  15. +8 −29 src/3d/{abstract3drenderer.h → vectorlayer3drenderer.h}
  16. +35 −0 src/app/3d/qgsphongmaterialwidget.cpp
  17. +27 −0 src/app/3d/qgsphongmaterialwidget.h
  18. +38 −0 src/app/3d/qgspolygon3dsymbolwidget.cpp
  19. +26 −0 src/app/3d/qgspolygon3dsymbolwidget.h
  20. +88 −0 src/app/3d/qgsvectorlayer3drendererwidget.cpp
  21. +43 −0 src/app/3d/qgsvectorlayer3drendererwidget.h
  22. +7 −0 src/app/CMakeLists.txt
  23. +2 −3 src/app/qgisapp.cpp
  24. +31 −0 src/app/qgslayerstylingwidget.cpp
  25. +5 −0 src/app/qgslayerstylingwidget.h
  26. +45 −0 src/core/3d/qgs3drendererregistry.cpp
  27. +61 −0 src/core/3d/qgs3drendererregistry.h
  28. +11 −0 src/core/3d/qgsabstract3drenderer.cpp
  29. +35 −0 src/core/3d/qgsabstract3drenderer.h
  30. +7 −0 src/core/CMakeLists.txt
  31. +8 −0 src/core/qgsapplication.cpp
  32. +9 −0 src/core/qgsapplication.h
  33. +17 −0 src/core/qgsmaplayer.cpp
  34. +24 −0 src/core/qgsmaplayer.h
  35. +94 −0 src/ui/3d/phongmaterialwidget.ui
  36. +110 −0 src/ui/3d/polygon3dsymbolwidget.ui
  37. +8 −8 src/ui/symbollayer/widget_simplefill.ui
@@ -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}")
@@ -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

@@ -570,6 +570,7 @@
<file>themes/default/mGeoPackage.svg</file>
<file>themes/default/mActionAddGeoPackageLayer.svg</file>
<file>icons/qgis_icon.svg</file>
<file>themes/default/3d.svg</file>
</qresource>
<qresource prefix="/images/tips">
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg12"
version="1.1"
width="16"
height="16">
<metadata
id="metadata18">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs16" />
<path
d="M 2.3348556,4.5414044 8.0212426,8.3776059 13.466994,4.7037083 7.7806076,0.86750671 Z"
style="fill:#f79191;fill-opacity:1;fill-rule:evenodd;stroke:#a40000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4535" />
<path
d="M 8.6635732,9.3611399 V 14.964189 L 14.109324,11.290292 V 5.6872423 Z"
style="fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#c4a000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4537" />
<path
d="m 1.6730308,5.5249384 5.686387,3.8362015 v 5.6030491 l -5.686387,-3.836201 z"
style="fill:#8ae234;fill-opacity:1;fill-rule:evenodd;stroke:#4e9a06;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4539" />
</svg>
@@ -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.
@@ -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();
@@ -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
)
@@ -1,9 +1,9 @@
#include "map3d.h"

#include "abstract3drenderer.h"
#include "flatterraingenerator.h"
#include "demterraingenerator.h"
//#include "quantizedmeshterraingenerator.h"
#include "vectorlayer3drenderer.h"

#include <QDomDocument>
#include <QDomElement>
@@ -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 );
}
}
@@ -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<Abstract3DRenderer *> renderers; //!< Stuff to render as 3D object
QList<QgsAbstract3DRenderer *> renderers; //!< Stuff to render as 3D object

bool skybox; //!< Whether to render skybox
QString skyboxFileBase;
@@ -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 )
{
}

@@ -8,7 +8,7 @@
#include <Qt3DLogic/QFrameAction>

#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<QgsMapLayer *>( 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 );
}
}
@@ -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<ChunkedEntity *> chunkEntities;
//! Keeps track of entities that belong to a particular layer
QMap<QgsMapLayer *, Qt3DCore::QEntity *> mLayerEntities;
};

#endif // SCENE_H
@@ -5,10 +5,10 @@
#include <Qt3DRender>
#include <Qt3DExtras>

#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();

@@ -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;

0 comments on commit ba7573a

Please sign in to comment.
You can’t perform that action at this time.