Skip to content

Commit

Permalink
[feature] [3d] [mesh] Display mesh faces in 3D view as terrain
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterPetrik committed Jan 16, 2019
1 parent 83340d0 commit d695c4b
Show file tree
Hide file tree
Showing 22 changed files with 1,040 additions and 5 deletions.
7 changes: 7 additions & 0 deletions src/3d/CMakeLists.txt
Expand Up @@ -17,6 +17,7 @@ SET(QGIS_3D_SRCS
qgstessellatedpolygongeometry.cpp
qgstilingscheme.cpp
qgsvectorlayer3drenderer.cpp
qgsmeshlayer3drenderer.cpp
qgswindow3dengine.cpp

chunks/qgschunkboundsentity_p.cpp
Expand All @@ -31,6 +32,8 @@ SET(QGIS_3D_SRCS
symbols/qgsabstract3dsymbol.cpp
symbols/qgsline3dsymbol.cpp
symbols/qgsline3dsymbol_p.cpp
symbols/qgsmesh3dsymbol.cpp
symbols/qgsmesh3dsymbol_p.cpp
symbols/qgspoint3dsymbol.cpp
symbols/qgspoint3dsymbol_p.cpp
symbols/qgspolygon3dsymbol.cpp
Expand Down Expand Up @@ -99,6 +102,7 @@ SET(QGIS_3D_HDRS
qgstessellatedpolygongeometry.h
qgstilingscheme.h
qgsvectorlayer3drenderer.h
qgsmeshlayer3drenderer.h
qgswindow3dengine.h

chunks/qgschunkedentity_p.h
Expand All @@ -110,6 +114,8 @@ SET(QGIS_3D_HDRS
symbols/qgsabstract3dsymbol.h
symbols/qgsline3dsymbol.h
symbols/qgsline3dsymbol_p.h
symbols/qgsmesh3dsymbol.h
symbols/qgsmesh3dsymbol_p.h
symbols/qgspoint3dsymbol.h
symbols/qgspoint3dsymbol_p.h
symbols/qgspolygon3dsymbol.h
Expand All @@ -135,6 +141,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/src/core/
${CMAKE_SOURCE_DIR}/src/core/geometry
${CMAKE_SOURCE_DIR}/src/core/raster
${CMAKE_SOURCE_DIR}/src/core/mesh
${CMAKE_SOURCE_DIR}/src/core/symbology
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/expression
Expand Down
7 changes: 6 additions & 1 deletion src/3d/qgs3dmapscene.cpp
Expand Up @@ -41,13 +41,14 @@
#include "qgscameracontroller.h"
#include "qgschunkedentity_p.h"
#include "qgschunknode_p.h"
#include "qgsmeshlayer.h"
#include "qgsmeshlayer3drenderer.h"
#include "qgsterrainentity_p.h"
#include "qgsterraingenerator.h"
#include "qgstessellatedpolygongeometry.h"
#include "qgsvectorlayer.h"
#include "qgsvectorlayer3drenderer.h"


Qgs3DMapScene::Qgs3DMapScene( const Qgs3DMapSettings &map, QgsAbstract3DEngine *engine )
: mMap( map )
, mEngine( engine )
Expand Down Expand Up @@ -538,6 +539,10 @@ void Qgs3DMapScene::addLayerEntity( QgsMapLayer *layer )
{
static_cast<QgsVectorLayer3DRenderer *>( renderer )->setLayer( static_cast<QgsVectorLayer *>( layer ) );
}
else if ( layer->type() == QgsMapLayer::MeshLayer && renderer->type() == QLatin1String( "mesh" ) )
{
static_cast<QgsMeshLayer3DRenderer *>( renderer )->setLayer( static_cast<QgsMeshLayer *>( layer ) );
}

Qt3DCore::QEntity *newEntity = renderer->createEntity( mMap );
if ( newEntity )
Expand Down
5 changes: 5 additions & 0 deletions src/3d/qgs3dmapsettings.cpp
Expand Up @@ -20,6 +20,7 @@
#include "qgsdemterraingenerator.h"
//#include "quantizedmeshterraingenerator.h"
#include "qgsvectorlayer3drenderer.h"
#include "qgsmeshlayer3drenderer.h"

#include <QDomDocument>
#include <QDomElement>
Expand Down Expand Up @@ -161,6 +162,10 @@ void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteConte
{
renderer = new QgsVectorLayer3DRenderer;
}
else if ( type == QLatin1String( "mesh" ) )
{
renderer = new QgsMeshLayer3DRenderer;
}

if ( renderer )
{
Expand Down
112 changes: 112 additions & 0 deletions src/3d/qgsmeshlayer3drenderer.cpp
@@ -0,0 +1,112 @@
/***************************************************************************
qgsmeshlayer3drenderer.cpp
--------------------------
Date : January 2019
Copyright : (C) 2019 by Peter Petrik
Email : zilolv at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsmeshlayer3drenderer.h"

#include "qgsmeshlayer3drenderer.h"
#include "qgsmesh3dsymbol.h"
#include "qgsmesh3dsymbol_p.h"

#include "qgsmeshlayer.h"
#include "qgsxmlutils.h"


QgsMeshLayer3DRendererMetadata::QgsMeshLayer3DRendererMetadata()
: Qgs3DRendererAbstractMetadata( QStringLiteral( "mesh" ) )
{
}

QgsAbstract3DRenderer *QgsMeshLayer3DRendererMetadata::createRenderer( QDomElement &elem, const QgsReadWriteContext &context )
{
QgsMeshLayer3DRenderer *r = new QgsMeshLayer3DRenderer;
r->readXml( elem, context );
return r;
}


// ---------


QgsMeshLayer3DRenderer::QgsMeshLayer3DRenderer( QgsMesh3DSymbol *s )
: mSymbol( s )
{
}

QgsMeshLayer3DRenderer *QgsMeshLayer3DRenderer::clone() const
{
QgsMeshLayer3DRenderer *r = new QgsMeshLayer3DRenderer( mSymbol ? ( QgsMesh3DSymbol * )mSymbol->clone() : nullptr );
r->mLayerRef = mLayerRef;
return r;
}

void QgsMeshLayer3DRenderer::setLayer( QgsMeshLayer *layer )
{
mLayerRef = QgsMapLayerRef( layer );
}

QgsMeshLayer *QgsMeshLayer3DRenderer::layer() const
{
return qobject_cast<QgsMeshLayer *>( mLayerRef.layer );
}

void QgsMeshLayer3DRenderer::setSymbol( QgsMesh3DSymbol *symbol )
{
mSymbol.reset( symbol );
}

const QgsMesh3DSymbol *QgsMeshLayer3DRenderer::symbol() const
{
return mSymbol.get();
}

Qt3DCore::QEntity *QgsMeshLayer3DRenderer::createEntity( const Qgs3DMapSettings &map ) const
{
QgsMeshLayer *vl = layer();

if ( !mSymbol || !vl )
return nullptr;

return new QgsMesh3DSymbolEntity( map, vl, *static_cast<QgsMesh3DSymbol *>( mSymbol.get() ) );
}

void QgsMeshLayer3DRenderer::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
{
QDomDocument doc = elem.ownerDocument();

elem.setAttribute( QStringLiteral( "layer" ), mLayerRef.layerId );

QDomElement elemSymbol = doc.createElement( QStringLiteral( "symbol" ) );
if ( mSymbol )
{
elemSymbol.setAttribute( QStringLiteral( "type" ), mSymbol->type() );
mSymbol->writeXml( elemSymbol, context );
}
elem.appendChild( elemSymbol );
}

void QgsMeshLayer3DRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
{
mLayerRef = QgsMapLayerRef( elem.attribute( QStringLiteral( "layer" ) ) );

QDomElement elemSymbol = elem.firstChildElement( QStringLiteral( "symbol" ) );
QgsMesh3DSymbol *symbol = new QgsMesh3DSymbol;
symbol->readXml( elemSymbol, context );
mSymbol.reset( symbol );
}

void QgsMeshLayer3DRenderer::resolveReferences( const QgsProject &project )
{
mLayerRef.setLayer( project.mapLayer( mLayerRef.layerId ) );
}
92 changes: 92 additions & 0 deletions src/3d/qgsmeshlayer3drenderer.h
@@ -0,0 +1,92 @@
/***************************************************************************
qgsmeshlayer3drenderer.h
------------------------
Date : January 2019
Copyright : (C) 2019 by Peter Petrik
Email : zilolv at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSMESHLAYER3DRENDERER_H
#define QGSMESHLAYER3DRENDERER_H

#include "qgis_3d.h"

#include "qgs3drendererregistry.h"
#include "qgsabstract3drenderer.h"
#include "qgsmesh3dsymbol.h"

#include "qgsphongmaterialsettings.h"
#include "qgsmaplayerref.h"

#include <QObject>

class QgsMeshLayer;


/**
* \ingroup core
* Metadata for mesh layer 3D renderer to allow creation of its instances from XML
*
* \warning This is not considered stable API, and may change in future QGIS releases
*
* \since QGIS 3.6
*/
class _3D_EXPORT QgsMeshLayer3DRendererMetadata : public Qgs3DRendererAbstractMetadata
{
public:
QgsMeshLayer3DRendererMetadata();

//! Creates an instance of a 3D renderer based on a DOM element with renderer configuration
QgsAbstract3DRenderer *createRenderer( QDomElement &elem, const QgsReadWriteContext &context ) override SIP_FACTORY;
};


/**
* \ingroup core
* 3D renderer that renders all mesh triangles of a mesh layer.
* \since QGIS 3.6
*/
class _3D_EXPORT QgsMeshLayer3DRenderer : public QgsAbstract3DRenderer
{
public:
//! Takes ownership of the symbol object
explicit QgsMeshLayer3DRenderer( QgsMesh3DSymbol *s SIP_TRANSFER = nullptr );

//! Sets vector layer associated with the renderer
void setLayer( QgsMeshLayer *layer );
//! Returns mesh layer associated with the renderer
QgsMeshLayer *layer() const;

//! Sets 3D symbol associated with the renderer
void setSymbol( QgsMesh3DSymbol *symbol SIP_TRANSFER );
//! Returns 3D symbol associated with the renderer
const QgsMesh3DSymbol *symbol() const;

QString type() const override { return "mesh"; }
QgsMeshLayer3DRenderer *clone() const override SIP_FACTORY;
Qt3DCore::QEntity *createEntity( const Qgs3DMapSettings &map ) const override SIP_SKIP;

void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const override;
void readXml( const QDomElement &elem, const QgsReadWriteContext &context ) override;
void resolveReferences( const QgsProject &project ) override;


private:
QgsMapLayerRef mLayerRef; //!< Layer used to extract polygons from
std::unique_ptr<QgsMesh3DSymbol> mSymbol; //!< 3D symbol that defines appearance

private:
#ifdef SIP_RUN
QgsMeshLayer3DRenderer( const QgsMeshLayer3DRenderer & );
QgsMeshLayer3DRenderer &operator=( const QgsMeshLayer3DRenderer & );
#endif
};

#endif // QGSMESHLAYER3DRENDERER_H
61 changes: 61 additions & 0 deletions src/3d/symbols/qgsmesh3dsymbol.cpp
@@ -0,0 +1,61 @@
/***************************************************************************
qgsmesh3dsymbol.cpp
-------------------
Date : January 2019
Copyright : (C) 2019 by Peter Petrik
Email : zilolv at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsmesh3dsymbol.h"

#include "qgs3dutils.h"

QgsAbstract3DSymbol *QgsMesh3DSymbol::clone() const
{
return new QgsMesh3DSymbol( *this );
}

void QgsMesh3DSymbol::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
{
Q_UNUSED( context );

QDomDocument doc = elem.ownerDocument();

QDomElement elemDataProperties = doc.createElement( QStringLiteral( "data" ) );
elemDataProperties.setAttribute( QStringLiteral( "alt-clamping" ), Qgs3DUtils::altClampingToString( mAltClamping ) );
elemDataProperties.setAttribute( QStringLiteral( "height" ), mHeight );
elemDataProperties.setAttribute( QStringLiteral( "add-back-faces" ), mAddBackFaces ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
elem.appendChild( elemDataProperties );

QDomElement elemMaterial = doc.createElement( QStringLiteral( "material" ) );
mMaterial.writeXml( elemMaterial );
elem.appendChild( elemMaterial );

QDomElement elemDDP = doc.createElement( QStringLiteral( "data-defined-properties" ) );
mDataDefinedProperties.writeXml( elemDDP, propertyDefinitions() );
elem.appendChild( elemDDP );
}

void QgsMesh3DSymbol::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
{
Q_UNUSED( context );

QDomElement elemDataProperties = elem.firstChildElement( QStringLiteral( "data" ) );
mAltClamping = Qgs3DUtils::altClampingFromString( elemDataProperties.attribute( QStringLiteral( "alt-clamping" ) ) );
mHeight = elemDataProperties.attribute( QStringLiteral( "height" ) ).toFloat();
mAddBackFaces = elemDataProperties.attribute( QStringLiteral( "add-back-faces" ) ).toInt();

QDomElement elemMaterial = elem.firstChildElement( QStringLiteral( "material" ) );
mMaterial.readXml( elemMaterial );

QDomElement elemDDP = elem.firstChildElement( QStringLiteral( "data-defined-properties" ) );
if ( !elemDDP.isNull() )
mDataDefinedProperties.readXml( elemDDP, propertyDefinitions() );
}

0 comments on commit d695c4b

Please sign in to comment.