Add RGB rendering

This commit is contained in:
NEDJIMAbelgacem 2020-11-26 00:08:25 +01:00 committed by Martin Dobias
parent 5be6a17662
commit d0cb30e189
10 changed files with 238 additions and 12 deletions

View File

@ -35,6 +35,8 @@ class QgsPointCloud3DSymbol : QgsAbstract3DSymbol
SingleColor,
//! Render the point cloud with a color ramp
ColorRamp,
//! Render the RGB colors of the point cloud
RGBRendering
};
QgsPointCloud3DSymbol( QgsPointCloudLayer *layer, QgsPointCloud3DSymbol::RenderingStyle style );
@ -256,6 +258,51 @@ Sets the minimum and maximum values used when classifying colors in the color ra
};
class QgsRGBPointCloud3DSymbol : QgsPointCloud3DSymbol
{
%Docstring
3D symbol that draws point cloud geometries as 3D objects using RGB colors in the dataset
.. 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:
QgsRGBPointCloud3DSymbol( QgsPointCloudLayer *layer );
%Docstring
Constructor for QgsRGBPointCloud3DSymbol
%End
virtual QgsAbstract3DSymbol *clone() const /Factory/;
virtual void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const;
virtual void readXml( const QDomElement &elem, const QgsReadWriteContext &context );
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 *
* *

View File

@ -127,6 +127,9 @@ void QgsPointCloudLayer3DRenderer::readXml( const QDomElement &elem, const QgsRe
case QgsPointCloud3DSymbol::RenderingStyle::ColorRamp:
mSymbol.reset( new QgsColorRampPointCloud3DSymbol( layer() ) );
break;
case QgsPointCloud3DSymbol::RenderingStyle::RGBRendering:
mSymbol.reset( new QgsRGBPointCloud3DSymbol( layer() ) );
break;
}
mSymbol->readXml( elemSymbol, context );
}

View File

@ -45,23 +45,26 @@
///@cond PRIVATE
QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent, const QgsPointCloud3DSymbolHandler::PointData &data )
QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent, const QgsPointCloud3DSymbolHandler::PointData &data, QgsPointCloud3DSymbol *symbol )
: Qt3DRender::QGeometry( parent )
, mPositionAttribute( new Qt3DRender::QAttribute( this ) )
, mParameterAttribute( new Qt3DRender::QAttribute( this ) )
, mColorAttribute( new Qt3DRender::QAttribute( this ) )
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
, mVertexBuffer( new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer, this ) )
#else
, mVertexBuffer( new Qt3DRender::QBuffer( this ) )
#endif
, mRenderingStyle( symbol->renderingStyle() )
{
unsigned int byte_stride = mRenderingStyle == QgsPointCloud3DSymbol::RenderingStyle::RGBRendering ? 28 : 16;
mPositionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
mPositionAttribute->setBuffer( mVertexBuffer );
mPositionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
mPositionAttribute->setVertexSize( 3 );
mPositionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
mPositionAttribute->setByteOffset( 0 );
mPositionAttribute->setByteStride( 16 );
mPositionAttribute->setByteStride( byte_stride );
mParameterAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
mParameterAttribute->setBuffer( mVertexBuffer );
@ -69,18 +72,33 @@ QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent, const
mParameterAttribute->setVertexSize( 1 );
mParameterAttribute->setName( "vertexParameter" );
mParameterAttribute->setByteOffset( 12 );
mParameterAttribute->setByteStride( 16 );
mParameterAttribute->setByteStride( byte_stride );
addAttribute( mPositionAttribute );
addAttribute( mParameterAttribute );
if ( mRenderingStyle == QgsPointCloud3DSymbol::RenderingStyle::RGBRendering )
{
mColorAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
mColorAttribute->setBuffer( mVertexBuffer );
mColorAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
mColorAttribute->setVertexSize( 3 );
mColorAttribute->setName( QStringLiteral( "vertexColor" ) );
mColorAttribute->setByteOffset( 16 );
mColorAttribute->setByteStride( byte_stride );
addAttribute( mColorAttribute );
}
makeVertexBuffer( data );
}
void QgsPointCloud3DGeometry::makeVertexBuffer( const QgsPointCloud3DSymbolHandler::PointData &data )
{
QByteArray vertexBufferData;
vertexBufferData.resize( data.positions.size() * 4 * sizeof( float ) );
if ( mRenderingStyle == QgsPointCloud3DSymbol::RenderingStyle::RGBRendering )
vertexBufferData.resize( data.positions.size() * 7 * sizeof( float ) );
else
vertexBufferData.resize( data.positions.size() * 4 * sizeof( float ) );
float *rawVertexArray = reinterpret_cast<float *>( vertexBufferData.data() );
int idx = 0;
Q_ASSERT( data.positions.count() == data.parameter.count() );
@ -90,6 +108,12 @@ void QgsPointCloud3DGeometry::makeVertexBuffer( const QgsPointCloud3DSymbolHandl
rawVertexArray[idx++] = data.positions.at( i ).y();
rawVertexArray[idx++] = data.positions.at( i ).z();
rawVertexArray[idx++] = data.parameter.at( i );
if ( mRenderingStyle == QgsPointCloud3DSymbol::RenderingStyle::RGBRendering )
{
rawVertexArray[idx++] = data.colors.at( i ).x();
rawVertexArray[idx++] = data.colors.at( i ).y();
rawVertexArray[idx++] = data.colors.at( i ).z();
}
}
mVertexCount = data.positions.size();
@ -131,6 +155,13 @@ void QgsPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const In
}
}
if ( mSymbol.get()->renderingStyle() == QgsPointCloud3DSymbol::RGBRendering )
{
attributes.push_back( QgsPointCloudAttribute( "Red", QgsPointCloudAttribute::DataType::Short ) );
attributes.push_back( QgsPointCloudAttribute( "Green", QgsPointCloudAttribute::DataType::Short ) );
attributes.push_back( QgsPointCloudAttribute( "Blue", QgsPointCloudAttribute::DataType::Short ) );
}
QgsPointCloudRequest request;
request.setAttributes( attributes );
std::unique_ptr<QgsPointCloudBlock> block( pc->nodeData( n, request ) );
@ -180,12 +211,33 @@ void QgsPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const In
outNormal.positions.push_back( QVector3D( p.x(), p.y(), p.z() ) );
if ( parameterAttribute && parameterAttribute->name() == "X" )
outNormal.parameter.push_back( x );
if ( parameterAttribute && parameterAttribute->name() == "Y" )
else if ( parameterAttribute && parameterAttribute->name() == "Y" )
outNormal.parameter.push_back( y );
if ( parameterAttribute && parameterAttribute->name() == "Z" )
else if ( parameterAttribute && parameterAttribute->name() == "Z" )
outNormal.parameter.push_back( z );
else
outNormal.parameter.push_back( iParam );
if ( mSymbol.get()->renderingStyle() == QgsPointCloud3DSymbol::RGBRendering )
{
QVector3D color( 0.0f, 0.0f, 0.0f );
if ( recordSize > 10 )
{
short ir = *( short * )( ptr + i * recordSize + 12 );
color.setX( ( ( float )ir ) / 256.0f );
}
if ( recordSize > 12 )
{
short ig = *( short * )( ptr + i * recordSize + 14 );
color.setY( ( ( float )ig ) / 256.0f );
}
if ( recordSize > 14 )
{
short ib = *( short * )( ptr + i * recordSize + 16 );
color.setZ( ( ( float )ib ) / 256.0f );
}
outNormal.colors.push_back( color );
}
}
}
@ -203,7 +255,7 @@ void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const
return;
// Geometry
QgsPointCloud3DGeometry *geom = new QgsPointCloud3DGeometry( parent, out );
QgsPointCloud3DGeometry *geom = new QgsPointCloud3DGeometry( parent, out, mSymbol.get() );
Qt3DRender::QGeometryRenderer *gr = new Qt3DRender::QGeometryRenderer;
gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
gr->setVertexCount( out.positions.count() );
@ -225,6 +277,9 @@ void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const
case QgsPointCloud3DSymbol::RenderingStyle::ColorRamp:
mat = constructMaterial( dynamic_cast<QgsColorRampPointCloud3DSymbol *>( mSymbol.get() ) );
break;
case QgsPointCloud3DSymbol::RenderingStyle::RGBRendering:
mat = constructMaterial( dynamic_cast<QgsRGBPointCloud3DSymbol *>( mSymbol.get() ) );
break;
}
Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram( mat );
@ -247,6 +302,9 @@ void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const
case QgsPointCloud3DSymbol::RenderingStyle::ColorRamp:
pointSize->setValue( dynamic_cast<QgsColorRampPointCloud3DSymbol *>( mSymbol.get() )->pointSize() );
break;
case QgsPointCloud3DSymbol::RenderingStyle::RGBRendering:
pointSize->setValue( dynamic_cast<QgsRGBPointCloud3DSymbol *>( mSymbol.get() )->pointSize() );
break;
}
renderPass->addRenderState( pointSize );
@ -305,9 +363,8 @@ Qt3DRender::QMaterial *QgsPointCloud3DSymbolHandler::constructMaterial( QgsColor
mat->addParameter( renderingStyle );
Qt3DRender::QParameter *pointSizeParameter = new Qt3DRender::QParameter( "u_pointSize", QVariant::fromValue( symbol->pointSize() ) );
mat->addParameter( pointSizeParameter );
// Qt3DRender::QParameter *renderingParameter = new Qt3DRender::QParameter( "u_renderingParameter", symbol->renderingParameter() );
// mat->addParameter( renderingParameter );
QgsColorRampShader colorRampShader = symbol->colorRampShader();
// Create the texture to pass the color ramp
Qt3DRender::QTexture1D *colorRampTexture = nullptr;
if ( colorRampShader.colorRampItemList().count() > 0 )
@ -317,6 +374,7 @@ Qt3DRender::QMaterial *QgsPointCloud3DSymbolHandler::constructMaterial( QgsColor
colorRampTexture->setMinificationFilter( Qt3DRender::QTexture1D::Linear );
colorRampTexture->setMagnificationFilter( Qt3DRender::QTexture1D::Linear );
}
// Parameters
Qt3DRender::QParameter *colorRampTextureParameter = new Qt3DRender::QParameter( "u_colorRampTexture", colorRampTexture );
mat->addParameter( colorRampTextureParameter );
@ -328,6 +386,16 @@ Qt3DRender::QMaterial *QgsPointCloud3DSymbolHandler::constructMaterial( QgsColor
return mat;
}
Qt3DRender::QMaterial *QgsPointCloud3DSymbolHandler::constructMaterial( QgsRGBPointCloud3DSymbol *symbol )
{
Qt3DRender::QMaterial *mat = new Qt3DRender::QMaterial;
Qt3DRender::QParameter *renderingStyle = new Qt3DRender::QParameter( "u_renderingStyle", symbol->renderingStyle() );
mat->addParameter( renderingStyle );
Qt3DRender::QParameter *pointSizeParameter = new Qt3DRender::QParameter( "u_pointSize", QVariant::fromValue( symbol->pointSize() ) );
mat->addParameter( pointSizeParameter );
return mat;
}
QgsPointCloudLayerChunkLoader::QgsPointCloudLayerChunkLoader( const QgsPointCloudLayerChunkLoaderFactory *factory, QgsChunkNode *node, QgsPointCloud3DSymbol *symbol )
: QgsChunkLoader( node )
, mFactory( factory )

View File

@ -65,6 +65,7 @@ class QgsPointCloud3DSymbolHandler // : public QgsFeature3DHandler
{
QVector<QVector3D> positions; // contains triplets of float x,y,z for each point
QVector<float> parameter;
QVector<QVector3D> colors;
};
protected:
@ -81,6 +82,7 @@ class QgsPointCloud3DSymbolHandler // : public QgsFeature3DHandler
Qt3DRender::QMaterial *constructMaterial( QgsNoRenderingPointCloud3DSymbol *symbol );
Qt3DRender::QMaterial *constructMaterial( QgsSingleColorPointCloud3DSymbol *symbol );
Qt3DRender::QMaterial *constructMaterial( QgsColorRampPointCloud3DSymbol *symbol );
Qt3DRender::QMaterial *constructMaterial( QgsRGBPointCloud3DSymbol *symbol );
void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected );
@ -99,15 +101,18 @@ class QgsPointCloud3DSymbolHandler // : public QgsFeature3DHandler
class QgsPointCloud3DGeometry: public Qt3DRender::QGeometry
{
public:
QgsPointCloud3DGeometry( Qt3DCore::QNode *parent, const QgsPointCloud3DSymbolHandler::PointData &data );
QgsPointCloud3DGeometry( Qt3DCore::QNode *parent, const QgsPointCloud3DSymbolHandler::PointData &data, QgsPointCloud3DSymbol *symbol );
private:
void makeVertexBuffer( const QgsPointCloud3DSymbolHandler::PointData &data );
Qt3DRender::QAttribute *mPositionAttribute = nullptr;
Qt3DRender::QAttribute *mParameterAttribute = nullptr;
Qt3DRender::QAttribute *mColorAttribute = nullptr;
Qt3DRender::QBuffer *mVertexBuffer = nullptr;
int mVertexCount = 0;
QgsPointCloud3DSymbol::RenderingStyle mRenderingStyle;
};
/**

View File

@ -2,6 +2,7 @@
in float parameter;
in vec3 pointColor;
out vec4 color;
// Sets the redering style, 0: unique color, 1: color ramp shader of terrain, 2: color ramp shader of 2D rendering
@ -147,5 +148,8 @@ void main(void)
case 2: // color ramp
color = colorRamp();
break;
case 3: // RGB
color = vec4(pointColor, 1.0f);
break;
}
}

View File

@ -10,8 +10,10 @@ uniform int u_renderingParameter;
in vec3 vertexPosition;
in float vertexParameter;
in vec3 vertexColor;
out float parameter;
out vec3 pointColor;
void main(void)
{
@ -25,4 +27,5 @@ void main(void)
//gl_PointSize = 100.0;
parameter = vertexParameter;
pointColor = vertexColor;
}

View File

@ -182,3 +182,39 @@ void QgsColorRampPointCloud3DSymbol::setColorRampShaderMinMax( double min, doubl
mColorRampShaderMin = min;
mColorRampShaderMax = max;
}
// QgsRGBPointCloud3DSymbol
QgsRGBPointCloud3DSymbol::QgsRGBPointCloud3DSymbol( QgsPointCloudLayer *layer )
: QgsPointCloud3DSymbol( layer, QgsPointCloud3DSymbol::RenderingStyle::RGBRendering )
{
}
QgsAbstract3DSymbol *QgsRGBPointCloud3DSymbol::clone() const
{
QgsRGBPointCloud3DSymbol *result = new QgsRGBPointCloud3DSymbol( mLayer );
result->mPointSize = mPointSize;
copyBaseSettings( result );
return result;
}
void QgsRGBPointCloud3DSymbol::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
{
Q_UNUSED( context )
elem.setAttribute( QStringLiteral( "rendering-style" ), mRenderingStyle );
elem.setAttribute( QStringLiteral( "point-size" ), mPointSize );
}
void QgsRGBPointCloud3DSymbol::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
{
Q_UNUSED( context )
mRenderingStyle = static_cast< QgsPointCloud3DSymbol::RenderingStyle >( elem.attribute( "rendering-style", QStringLiteral( "3" ) ).toInt() );
mPointSize = elem.attribute( "point-size", QStringLiteral( "2.0" ) ).toFloat();
}
void QgsRGBPointCloud3DSymbol::setPointSize( float size )
{
mPointSize = size;
}

View File

@ -46,6 +46,8 @@ class _3D_EXPORT QgsPointCloud3DSymbol : public QgsAbstract3DSymbol
SingleColor,
//! Render the point cloud with a color ramp
ColorRamp,
//! Render the RGB colors of the point cloud
RGBRendering
};
//! Constructor for QgsPointCloud3DSymbol
@ -232,4 +234,39 @@ class _3D_EXPORT QgsColorRampPointCloud3DSymbol : public QgsPointCloud3DSymbol
double mColorRampShaderMax = 1.0;
};
/**
* \ingroup 3d
* 3D symbol that draws point cloud geometries as 3D objects using RGB colors in the dataset
*
* \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.
*
* \since QGIS 3.18
*/
class _3D_EXPORT QgsRGBPointCloud3DSymbol : public QgsPointCloud3DSymbol
{
public:
//! Constructor for QgsRGBPointCloud3DSymbol
QgsRGBPointCloud3DSymbol( QgsPointCloudLayer *layer );
QgsAbstract3DSymbol *clone() const override SIP_FACTORY;
void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const override;
void readXml( const QDomElement &elem, const QgsReadWriteContext &context ) override;
/**
* Returns the point size of the point cloud
* \see setPointSize( float size )
*/
float pointSize() const { return mPointSize; }
/**
* Sets the point size
* \see pointSize()
*/
void setPointSize( float size );
private:
float mPointSize;
};
#endif // QGSPOINTCLOUD3DSYMBOL_H

View File

@ -50,14 +50,14 @@ void QgsPointCloud3DSymbolWidget::setSymbol( QgsPointCloud3DSymbol *symbol )
break;
case QgsPointCloud3DSymbol::RenderingStyle::SingleColor:
{
QgsSingleColorPointCloud3DSymbol *symb = static_cast<QgsSingleColorPointCloud3DSymbol *>( symbol );
QgsSingleColorPointCloud3DSymbol *symb = dynamic_cast<QgsSingleColorPointCloud3DSymbol *>( symbol );
mPointSizeSpinBox->setValue( symb->pointSize() );
mSingleColorBtn->setColor( symb->singleColor() );
break;
}
case QgsPointCloud3DSymbol::RenderingStyle::ColorRamp:
{
QgsColorRampPointCloud3DSymbol *symb = static_cast<QgsColorRampPointCloud3DSymbol *>( symbol );
QgsColorRampPointCloud3DSymbol *symb = dynamic_cast<QgsColorRampPointCloud3DSymbol *>( symbol );
mPointSizeSpinBox->setValue( symb->pointSize() );
mRenderingParameterComboBox->setCurrentText( symb->renderingParameter() );
QgsColorRampShader shader = symb->colorRampShader();
@ -65,6 +65,12 @@ void QgsPointCloud3DSymbolWidget::setSymbol( QgsPointCloud3DSymbol *symbol )
mColorRampShaderWidget->setFromShader( symb->colorRampShader() );
break;
}
case QgsPointCloud3DSymbol::RenderingStyle::RGBRendering:
{
QgsRGBPointCloud3DSymbol *symb = dynamic_cast<QgsRGBPointCloud3DSymbol *>( symbol );
mPointSizeSpinBox->setValue( symb->pointSize() );
break;
}
}
onRenderingStyleChanged( symbol->renderingStyle() );
@ -101,6 +107,13 @@ QgsPointCloud3DSymbol *QgsPointCloud3DSymbolWidget::symbol() const
ret_symb = symb;
break;
}
case QgsPointCloud3DSymbol::RenderingStyle::RGBRendering:
{
QgsRGBPointCloud3DSymbol *symb = new QgsRGBPointCloud3DSymbol( mLayer );
symb->setPointSize( mPointSizeSpinBox->value() );
ret_symb = symb;
break;
}
}
return ret_symb;
}
@ -139,5 +152,10 @@ void QgsPointCloud3DSymbolWidget::onRenderingStyleChanged( int current )
mSingleColorFrame->setVisible( false );
mPointSizeFrame->setVisible( true );
break;
case QgsPointCloud3DSymbol::RenderingStyle::RGBRendering:
mColorRampFrame->setVisible( false );
mSingleColorFrame->setVisible( false );
mPointSizeFrame->setVisible( true );
break;
}
}

View File

@ -28,6 +28,11 @@
<string>Color ramp</string>
</property>
</item>
<item>
<property name="text">
<string>RGB rendering</string>
</property>
</item>
</widget>
</item>
<item row="7" column="0" colspan="4">