Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #40030 from NEDJIMAbelgacem/point-clouds-3d-gui
point-cloud 3D GUI
  • Loading branch information
nyalldawson committed Nov 18, 2020
2 parents 234bd31 + 952f1d9 commit af162a8
Show file tree
Hide file tree
Showing 23 changed files with 653 additions and 46 deletions.
1 change: 1 addition & 0 deletions python/3d/3d_auto.sip
Expand Up @@ -21,4 +21,5 @@
%Include auto_generated/symbols/qgsline3dsymbol.sip
%Include auto_generated/symbols/qgspoint3dsymbol.sip
%Include auto_generated/symbols/qgspolygon3dsymbol.sip
%Include auto_generated/symbols/qgspointcloud3dsymbol.sip
%Include auto_generated/qgs3dmapexportsettings.sip
12 changes: 12 additions & 0 deletions python/3d/auto_generated/qgspointcloudlayer3drenderer.sip.in
Expand Up @@ -43,6 +43,18 @@ Returns point cloud layer associated with the renderer
virtual QgsPointCloudLayer3DRenderer *clone() const /Factory/;


void setSymbol( QgsPointCloud3DSymbol *symbol /Transfer/ );
%Docstring
Sets the 3D ``symbol`` associated with the renderer.
Ownership of ``symbol`` is transferred to the renderer.

.. seealso:: :py:func:`symbol`
%End
const QgsPointCloud3DSymbol *symbol() const;
%Docstring
Returns 3D symbol associated with the renderer
%End

virtual void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const;

virtual void readXml( const QDomElement &elem, const QgsReadWriteContext &context );
Expand Down
81 changes: 81 additions & 0 deletions python/3d/auto_generated/symbols/qgspointcloud3dsymbol.sip.in
@@ -0,0 +1,81 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/3d/symbols/qgspointcloud3dsymbol.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsPointCloud3DSymbol : QgsAbstract3DSymbol
{
%Docstring
3D symbol that draws point cloud geometries as 3D objects.

.. warning::

This is not considered stable API, and may change in future QGIS releases. It is
exposed to the Python bindings as a tech preview only.

.. versionadded:: 3.18
%End

%TypeHeaderCode
#include "qgspointcloud3dsymbol.h"
%End
public:
QgsPointCloud3DSymbol();
%Docstring
Constructor for QgsPointCloud3DSymbol
%End
~QgsPointCloud3DSymbol();

virtual QString type() const;
virtual QgsAbstract3DSymbol *clone() const /Factory/;


virtual void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const;


virtual void readXml( const QDomElement &elem, const QgsReadWriteContext &context );


bool isEnabled() const;
%Docstring
Returns whether rendering for this symbol is enabled

.. seealso:: :py:func:`setIsEnabled`
%End

void setIsEnabled( bool enabled );
%Docstring
Sets whether rendering for this symbol is enabled

.. seealso:: :py:func:`isEnabled`
%End

float pointSize() const;
%Docstring
Returns the point size of the point cloud

.. seealso:: :py:func:`setPointSize`
%End

void setPointSize( float size );
%Docstring
Sets the point size

.. seealso:: :py:func:`pointSize`
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/3d/symbols/qgspointcloud3dsymbol.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
2 changes: 2 additions & 0 deletions src/3d/CMakeLists.txt
Expand Up @@ -70,6 +70,7 @@ set(QGIS_3D_SRCS
symbols/qgspoint3dsymbol_p.cpp
symbols/qgspolygon3dsymbol.cpp
symbols/qgspolygon3dsymbol_p.cpp
symbols/qgspointcloud3dsymbol.cpp

terrain/qgsdemterraingenerator.cpp
terrain/qgsdemterraintilegeometry_p.cpp
Expand Down Expand Up @@ -137,6 +138,7 @@ set(QGIS_3D_HDRS
symbols/qgspoint3dbillboardmaterial.h
symbols/qgspoint3dsymbol.h
symbols/qgspolygon3dsymbol.h
symbols/qgspointcloud3dsymbol.h

terrain/qgsdemterraingenerator.h
terrain/qgsflatterraingenerator.h
Expand Down
29 changes: 26 additions & 3 deletions src/3d/qgspointcloudlayer3drenderer.cpp
Expand Up @@ -24,7 +24,9 @@
#include "qgsxmlutils.h"
#include "qgsapplication.h"
#include "qgs3dsymbolregistry.h"
#include "qgspointcloud3dsymbol.h"

#include "qgis.h"

QgsPointCloudLayer3DRendererMetadata::QgsPointCloudLayer3DRendererMetadata()
: Qgs3DRendererAbstractMetadata( QStringLiteral( "pointcloud" ) )
Expand Down Expand Up @@ -64,6 +66,11 @@ QString QgsPointCloudLayer3DRenderer::type() const
QgsPointCloudLayer3DRenderer *QgsPointCloudLayer3DRenderer::clone() const
{
QgsPointCloudLayer3DRenderer *r = new QgsPointCloudLayer3DRenderer;
if ( mSymbol )
{
QgsAbstract3DSymbol *symbolClone = mSymbol->clone();
r->setSymbol( dynamic_cast<QgsPointCloud3DSymbol *>( symbolClone ) );
}
return r;
}

Expand All @@ -73,7 +80,12 @@ Qt3DCore::QEntity *QgsPointCloudLayer3DRenderer::createEntity( const Qgs3DMapSet
if ( !pcl || !pcl->dataProvider() || !pcl->dataProvider()->index() )
return nullptr;

return new QgsPointCloudLayerChunkedEntity( pcl->dataProvider()->index(), map );
return new QgsPointCloudLayerChunkedEntity( pcl->dataProvider()->index(), map, dynamic_cast<QgsPointCloud3DSymbol *>( mSymbol->clone() ) );
}

void QgsPointCloudLayer3DRenderer::setSymbol( QgsPointCloud3DSymbol *symbol )
{
mSymbol.reset( symbol );
}

void QgsPointCloudLayer3DRenderer::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
Expand All @@ -83,13 +95,24 @@ void QgsPointCloudLayer3DRenderer::writeXml( QDomElement &elem, const QgsReadWri
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 QgsPointCloudLayer3DRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
{
Q_UNUSED( context )

mLayerRef = QgsMapLayerRef( elem.attribute( QStringLiteral( "layer" ) ) );

QDomElement elemSymbol = elem.firstChildElement( QStringLiteral( "symbol" ) );
if ( !mSymbol )
mSymbol = qgis::make_unique< QgsPointCloud3DSymbol >();
mSymbol->readXml( elemSymbol, context );
}

void QgsPointCloudLayer3DRenderer::resolveReferences( const QgsProject &project )
Expand Down
11 changes: 11 additions & 0 deletions src/3d/qgspointcloudlayer3drenderer.h
Expand Up @@ -26,6 +26,7 @@
#include <QObject>

class QgsPointCloudLayer;
class QgsPointCloud3DSymbol;

#ifndef SIP_RUN

Expand Down Expand Up @@ -69,12 +70,22 @@ class _3D_EXPORT QgsPointCloudLayer3DRenderer : public QgsAbstract3DRenderer
QgsPointCloudLayer3DRenderer *clone() const override SIP_FACTORY;
Qt3DCore::QEntity *createEntity( const Qgs3DMapSettings &map ) const override SIP_SKIP;

/**
* Sets the 3D \a symbol associated with the renderer.
* Ownership of \a symbol is transferred to the renderer.
* \see symbol()
*/
void setSymbol( QgsPointCloud3DSymbol *symbol SIP_TRANSFER );
//! Returns 3D symbol associated with the renderer
const QgsPointCloud3DSymbol *symbol() const { return mSymbol.get(); }

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 mesh data from
std::unique_ptr< QgsPointCloud3DSymbol > mSymbol;

private:
#ifdef SIP_RUN
Expand Down
26 changes: 16 additions & 10 deletions src/3d/qgspointcloudlayerchunkloader_p.cpp
Expand Up @@ -26,6 +26,8 @@
#include "qgspoint3dsymbol.h"
#include "qgsphongmaterialsettings.h"

#include "qgspointcloud3dsymbol.h"

#include "qgsapplication.h"
#include "qgs3dsymbolregistry.h"
#include "qgspointcloudattribute.h"
Expand Down Expand Up @@ -93,9 +95,9 @@ void QgsPointCloud3DGeometry::makeVertexBuffer( const QgsPointCloud3DSymbolHandl
}


QgsPointCloud3DSymbolHandler::QgsPointCloud3DSymbolHandler()
QgsPointCloud3DSymbolHandler::QgsPointCloud3DSymbolHandler( QgsPointCloud3DSymbol *symbol )
{

mSymbol.reset( symbol );
}

bool QgsPointCloud3DSymbolHandler::prepare( const Qgs3DRenderContext &context )
Expand Down Expand Up @@ -167,6 +169,9 @@ void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const
// Material
Qt3DRender::QMaterial *mat = new Qt3DRender::QMaterial;

Qt3DRender::QParameter *pointSizeParameter = new Qt3DRender::QParameter( "u_pointSize", QVariant::fromValue( mSymbol->pointSize() ) );
mat->addParameter( pointSizeParameter );

Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram( mat );
shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/pointcloud.vert" ) ) ) );
shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/pointcloud.frag" ) ) ) );
Expand All @@ -176,6 +181,7 @@ void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const

Qt3DRender::QPointSize *pointSize = new Qt3DRender::QPointSize( renderPass );
pointSize->setSizeMode( Qt3DRender::QPointSize::Programmable ); // supported since OpenGL 3.2
pointSize->setValue( mSymbol->pointSize() );
renderPass->addRenderState( pointSize );

// without this filter the default forward renderer would not render this
Expand Down Expand Up @@ -206,7 +212,7 @@ void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const
}


QgsPointCloudLayerChunkLoader::QgsPointCloudLayerChunkLoader( const QgsPointCloudLayerChunkLoaderFactory *factory, QgsChunkNode *node )
QgsPointCloudLayerChunkLoader::QgsPointCloudLayerChunkLoader( const QgsPointCloudLayerChunkLoaderFactory *factory, QgsChunkNode *node, QgsPointCloud3DSymbol *symbol )
: QgsChunkLoader( node )
, mFactory( factory )
, mContext( factory->mMap )
Expand All @@ -219,8 +225,7 @@ QgsPointCloudLayerChunkLoader::QgsPointCloudLayerChunkLoader( const QgsPointClou

QgsDebugMsgLevel( QStringLiteral( "loading entity %1" ).arg( node->tileId().text() ), 2 );

QgsPointCloud3DSymbolHandler *handler = new QgsPointCloud3DSymbolHandler;
mHandler.reset( handler );
mHandler.reset( new QgsPointCloud3DSymbolHandler( symbol ) );

//
// this will be run in a background thread
Expand Down Expand Up @@ -274,17 +279,18 @@ Qt3DCore::QEntity *QgsPointCloudLayerChunkLoader::createEntity( Qt3DCore::QEntit
///////////////


QgsPointCloudLayerChunkLoaderFactory::QgsPointCloudLayerChunkLoaderFactory( const Qgs3DMapSettings &map, QgsPointCloudIndex *pc )
QgsPointCloudLayerChunkLoaderFactory::QgsPointCloudLayerChunkLoaderFactory( const Qgs3DMapSettings &map, QgsPointCloudIndex *pc, QgsPointCloud3DSymbol *symbol )
: mMap( map )
, mPointCloudIndex( pc )
{
mSymbol.reset( symbol );
}

QgsChunkLoader *QgsPointCloudLayerChunkLoaderFactory::createChunkLoader( QgsChunkNode *node ) const
{
QgsChunkNodeId id = node->tileId();
Q_ASSERT( mPointCloudIndex->hasNode( IndexedPointCloudNode( id.d, id.x, id.y, id.z ) ) );
return new QgsPointCloudLayerChunkLoader( this, node );
return new QgsPointCloudLayerChunkLoader( this, node, dynamic_cast<QgsPointCloud3DSymbol *>( mSymbol->clone() ) );
}

QgsAABB nodeBoundsToAABB( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset, QgsVector3D scale, const Qgs3DMapSettings &map );
Expand Down Expand Up @@ -343,12 +349,12 @@ QgsAABB nodeBoundsToAABB( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset
}


QgsPointCloudLayerChunkedEntity::QgsPointCloudLayerChunkedEntity( QgsPointCloudIndex *pc, const Qgs3DMapSettings &map )
QgsPointCloudLayerChunkedEntity::QgsPointCloudLayerChunkedEntity( QgsPointCloudIndex *pc, const Qgs3DMapSettings &map, QgsPointCloud3DSymbol *symbol )
: QgsChunkedEntity( 5, // max. allowed screen error (in pixels) -- // TODO
new QgsPointCloudLayerChunkLoaderFactory( map, pc ), true )
new QgsPointCloudLayerChunkLoaderFactory( map, pc, symbol ), true )
{
setUsingAdditiveStrategy( true );
setShowBoundingBoxes( true );
setShowBoundingBoxes( false );
}

QgsPointCloudLayerChunkedEntity::~QgsPointCloudLayerChunkedEntity()
Expand Down
25 changes: 19 additions & 6 deletions src/3d/qgspointcloudlayerchunkloader_p.h
Expand Up @@ -30,6 +30,7 @@
#include "qgschunkloader_p.h"
#include "qgsfeature3dhandler_p.h"
#include "qgschunkedentity_p.h"
#include "qgspointcloud3dsymbol.h"

#define SIP_NO_FILE

Expand All @@ -38,6 +39,8 @@ class QgsPointCloudLayer;
class IndexedPointCloudNode;
class QgsPointCloudIndex;

#include <memory>

#include <QFutureWatcher>
#include <Qt3DRender/QGeometry>
#include <Qt3DRender/QBuffer>
Expand All @@ -47,7 +50,7 @@ class QgsPointCloudIndex;
class QgsPointCloud3DSymbolHandler // : public QgsFeature3DHandler
{
public:
QgsPointCloud3DSymbolHandler( );
QgsPointCloud3DSymbolHandler( QgsPointCloud3DSymbol *symbol );

bool prepare( const Qgs3DRenderContext &context );// override;
void processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const Qgs3DRenderContext &context ); // override;
Expand Down Expand Up @@ -85,6 +88,8 @@ class QgsPointCloud3DSymbolHandler // : public QgsFeature3DHandler
// outputs
PointData outNormal; //!< Features that are not selected
// PointData outSelected; //!< Features that are selected

std::unique_ptr<QgsPointCloud3DSymbol> mSymbol;
};

class QgsPointCloud3DGeometry: public Qt3DRender::QGeometry
Expand All @@ -111,8 +116,11 @@ class QgsPointCloud3DGeometry: public Qt3DRender::QGeometry
class QgsPointCloudLayerChunkLoaderFactory : public QgsChunkLoaderFactory
{
public:
//! Constructs the factory
QgsPointCloudLayerChunkLoaderFactory( const Qgs3DMapSettings &map, QgsPointCloudIndex *pc );
/*
* Constructs the factory
* The factory takes ownership over the passed \a symbol
*/
QgsPointCloudLayerChunkLoaderFactory( const Qgs3DMapSettings &map, QgsPointCloudIndex *pc, QgsPointCloud3DSymbol *symbol );

//! Creates loader for the given chunk node. Ownership of the returned is passed to the caller.
virtual QgsChunkLoader *createChunkLoader( QgsChunkNode *node ) const override;
Expand All @@ -121,6 +129,7 @@ class QgsPointCloudLayerChunkLoaderFactory : public QgsChunkLoaderFactory

const Qgs3DMapSettings &mMap;
QgsPointCloudIndex *mPointCloudIndex;
std::unique_ptr< QgsPointCloud3DSymbol > mSymbol;
};


Expand All @@ -135,8 +144,12 @@ class QgsPointCloudLayerChunkLoaderFactory : public QgsChunkLoaderFactory
class QgsPointCloudLayerChunkLoader : public QgsChunkLoader
{
public:
//! Constructs the loader
QgsPointCloudLayerChunkLoader( const QgsPointCloudLayerChunkLoaderFactory *factory, QgsChunkNode *node );

/**
* Constructs the loader
* QgsPointCloudLayerChunkLoader takes ownership over symbol
*/
QgsPointCloudLayerChunkLoader( const QgsPointCloudLayerChunkLoaderFactory *factory, QgsChunkNode *node, QgsPointCloud3DSymbol *symbol );
~QgsPointCloudLayerChunkLoader() override;

virtual void cancel() override;
Expand Down Expand Up @@ -165,7 +178,7 @@ class QgsPointCloudLayerChunkedEntity : public QgsChunkedEntity
{
Q_OBJECT
public:
explicit QgsPointCloudLayerChunkedEntity( QgsPointCloudIndex *pc, const Qgs3DMapSettings &map );
explicit QgsPointCloudLayerChunkedEntity( QgsPointCloudIndex *pc, const Qgs3DMapSettings &map, QgsPointCloud3DSymbol *symbol );

~QgsPointCloudLayerChunkedEntity();
};
Expand Down

0 comments on commit af162a8

Please sign in to comment.