Skip to content
Permalink
Browse files

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 af162a8c7087028a9b2cab64f756830bc7bcd726
@@ -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
@@ -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 );
@@ -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 *
************************************************************************/
@@ -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
@@ -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
@@ -24,7 +24,9 @@
#include "qgsxmlutils.h"
#include "qgsapplication.h"
#include "qgs3dsymbolregistry.h"
#include "qgspointcloud3dsymbol.h"

#include "qgis.h"

QgsPointCloudLayer3DRendererMetadata::QgsPointCloudLayer3DRendererMetadata()
: Qgs3DRendererAbstractMetadata( QStringLiteral( "pointcloud" ) )
@@ -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;
}

@@ -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
@@ -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 )
@@ -26,6 +26,7 @@
#include <QObject>

class QgsPointCloudLayer;
class QgsPointCloud3DSymbol;

#ifndef SIP_RUN

@@ -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
@@ -26,6 +26,8 @@
#include "qgspoint3dsymbol.h"
#include "qgsphongmaterialsettings.h"

#include "qgspointcloud3dsymbol.h"

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


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

mSymbol.reset( symbol );
}

bool QgsPointCloud3DSymbolHandler::prepare( const Qgs3DRenderContext &context )
@@ -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" ) ) ) );
@@ -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
@@ -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 )
@@ -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
@@ -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 );
@@ -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()
@@ -30,6 +30,7 @@
#include "qgschunkloader_p.h"
#include "qgsfeature3dhandler_p.h"
#include "qgschunkedentity_p.h"
#include "qgspointcloud3dsymbol.h"

#define SIP_NO_FILE

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

#include <memory>

#include <QFutureWatcher>
#include <Qt3DRender/QGeometry>
#include <Qt3DRender/QBuffer>
@@ -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;
@@ -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
@@ -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;
@@ -121,6 +129,7 @@ class QgsPointCloudLayerChunkLoaderFactory : public QgsChunkLoaderFactory

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


@@ -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;
@@ -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();
};

0 comments on commit af162a8

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