31 #include <Qt3DRender/QGeometryRenderer>
32 #include <Qt3DRender/QAttribute>
33 #include <Qt3DRender/QTechnique>
34 #include <Qt3DRender/QShaderProgram>
35 #include <Qt3DRender/QGraphicsApiFilter>
36 #include <Qt3DRender/QEffect>
40 QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent,
unsigned int byteStride )
42 , mPositionAttribute( new
Qt3DRender::QAttribute( this ) )
43 , mParameterAttribute( new
Qt3DRender::QAttribute( this ) )
44 , mColorAttribute( new
Qt3DRender::QAttribute( this ) )
45 , mVertexBuffer( new
Qt3DRender::QBuffer( this ) )
46 , mByteStride( byteStride )
51 QgsSingleColorPointCloud3DGeometry::QgsSingleColorPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
52 : QgsPointCloud3DGeometry( parent, byteStride )
54 mPositionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
55 mPositionAttribute->setBuffer( mVertexBuffer );
56 mPositionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
57 mPositionAttribute->setVertexSize( 3 );
58 mPositionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
59 mPositionAttribute->setByteOffset( 0 );
60 mPositionAttribute->setByteStride( mByteStride );
61 addAttribute( mPositionAttribute );
62 makeVertexBuffer( data );
65 void QgsSingleColorPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
67 QByteArray vertexBufferData;
68 vertexBufferData.resize( data.positions.size() * mByteStride );
69 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
71 for (
int i = 0; i < data.positions.size(); ++i )
73 rawVertexArray[idx++] = data.positions.at( i ).x();
74 rawVertexArray[idx++] = data.positions.at( i ).y();
75 rawVertexArray[idx++] = data.positions.at( i ).z();
78 mVertexCount = data.positions.size();
79 mVertexBuffer->setData( vertexBufferData );
82 QgsColorRampPointCloud3DGeometry::QgsColorRampPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
83 : QgsPointCloud3DGeometry( parent, byteStride )
85 mPositionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
86 mPositionAttribute->setBuffer( mVertexBuffer );
87 mPositionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
88 mPositionAttribute->setVertexSize( 3 );
89 mPositionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
90 mPositionAttribute->setByteOffset( 0 );
91 mPositionAttribute->setByteStride( mByteStride );
92 addAttribute( mPositionAttribute );
93 mParameterAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
94 mParameterAttribute->setBuffer( mVertexBuffer );
95 mParameterAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
96 mParameterAttribute->setVertexSize( 1 );
97 mParameterAttribute->setName(
"vertexParameter" );
98 mParameterAttribute->setByteOffset( 12 );
99 mParameterAttribute->setByteStride( mByteStride );
100 addAttribute( mParameterAttribute );
101 makeVertexBuffer( data );
104 void QgsColorRampPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
106 QByteArray vertexBufferData;
107 vertexBufferData.resize( data.positions.size() * mByteStride );
108 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
110 Q_ASSERT( data.positions.size() == data.parameter.size() );
111 for (
int i = 0; i < data.positions.size(); ++i )
113 rawVertexArray[idx++] = data.positions.at( i ).x();
114 rawVertexArray[idx++] = data.positions.at( i ).y();
115 rawVertexArray[idx++] = data.positions.at( i ).z();
116 rawVertexArray[idx++] = data.parameter.at( i );
119 mVertexCount = data.positions.size();
120 mVertexBuffer->setData( vertexBufferData );
123 QgsRGBPointCloud3DGeometry::QgsRGBPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
124 : QgsPointCloud3DGeometry( parent, byteStride )
126 mPositionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
127 mPositionAttribute->setBuffer( mVertexBuffer );
128 mPositionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
129 mPositionAttribute->setVertexSize( 3 );
130 mPositionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
131 mPositionAttribute->setByteOffset( 0 );
132 mPositionAttribute->setByteStride( mByteStride );
133 addAttribute( mPositionAttribute );
134 mColorAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
135 mColorAttribute->setBuffer( mVertexBuffer );
136 mColorAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
137 mColorAttribute->setVertexSize( 3 );
138 mColorAttribute->setName( QStringLiteral(
"vertexColor" ) );
139 mColorAttribute->setByteOffset( 12 );
140 mColorAttribute->setByteStride( mByteStride );
141 addAttribute( mColorAttribute );
142 makeVertexBuffer( data );
145 void QgsRGBPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
147 QByteArray vertexBufferData;
148 vertexBufferData.resize( data.positions.size() * mByteStride );
149 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
151 Q_ASSERT( data.positions.size() == data.colors.size() );
152 for (
int i = 0; i < data.positions.size(); ++i )
154 rawVertexArray[idx++] = data.positions.at( i ).x();
155 rawVertexArray[idx++] = data.positions.at( i ).y();
156 rawVertexArray[idx++] = data.positions.at( i ).z();
157 rawVertexArray[idx++] = data.colors.at( i ).x();
158 rawVertexArray[idx++] = data.colors.at( i ).y();
159 rawVertexArray[idx++] = data.colors.at( i ).z();
161 mVertexCount = data.positions.size();
162 mVertexBuffer->setData( vertexBufferData );
165 QgsPointCloud3DSymbolHandler::QgsPointCloud3DSymbolHandler()
169 void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const QgsPointCloud3DRenderContext &context, QgsPointCloud3DSymbolHandler::PointData &out,
bool selected )
173 if ( out.positions.empty() )
177 Qt3DRender::QGeometry *geom = makeGeometry( parent, out, context.
symbol()->
byteStride() );
178 Qt3DRender::QGeometryRenderer *gr =
new Qt3DRender::QGeometryRenderer;
179 gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
180 gr->setVertexCount( out.positions.count() );
181 gr->setGeometry( geom );
184 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
187 Qt3DRender::QMaterial *mat =
new Qt3DRender::QMaterial;
191 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram( mat );
192 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/pointcloud.vert" ) ) ) );
193 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/pointcloud.frag" ) ) ) );
195 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass( mat );
196 renderPass->setShaderProgram( shaderProgram );
198 Qt3DRender::QPointSize *pointSize =
new Qt3DRender::QPointSize( renderPass );
199 pointSize->setSizeMode( Qt3DRender::QPointSize::Programmable );
201 renderPass->addRenderState( pointSize );
204 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
205 filterKey->setName( QStringLiteral(
"renderingStyle" ) );
206 filterKey->setValue(
"forward" );
208 Qt3DRender::QTechnique *technique =
new Qt3DRender::QTechnique;
209 technique->addRenderPass( renderPass );
210 technique->addFilterKey( filterKey );
211 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
212 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
213 technique->graphicsApiFilter()->setMajorVersion( 3 );
214 technique->graphicsApiFilter()->setMinorVersion( 1 );
216 Qt3DRender::QEffect *eff =
new Qt3DRender::QEffect;
217 eff->addTechnique( technique );
218 mat->setEffect( eff );
221 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
222 entity->addComponent( gr );
223 entity->addComponent( tr );
224 entity->addComponent( mat );
225 entity->setParent( parent );
233 if ( pc->
accessType() == QgsPointCloudIndex::AccessType::Local )
237 else if ( pc->
accessType() == QgsPointCloudIndex::AccessType::Remote )
239 bool loopAborted =
false;
251 block = req->
block();
258 QgsSingleColorPointCloud3DSymbolHandler::QgsSingleColorPointCloud3DSymbolHandler()
259 : QgsPointCloud3DSymbolHandler()
279 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
283 const char *ptr = block->
data();
291 bool alreadyPrintedDebug =
false;
293 for (
int i = 0; i < count; ++i )
298 const qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
299 const qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
300 const qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
302 double x = blockOffset.
x() + blockScale.
x() * ix;
303 double y = blockOffset.
y() + blockScale.
y() * iy;
304 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
311 if ( !alreadyPrintedDebug )
313 QgsDebugMsg( QStringLiteral(
"Error transforming point coordinate" ) );
314 alreadyPrintedDebug =
true;
319 outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
325 makeEntity( parent, context, outNormal,
false );
328 Qt3DRender::QGeometry *QgsSingleColorPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
330 return new QgsSingleColorPointCloud3DGeometry( parent, data, byteStride );
333 QgsColorRampPointCloud3DSymbolHandler::QgsColorRampPointCloud3DSymbolHandler()
334 : QgsPointCloud3DSymbolHandler()
348 const int xOffset = 0;
355 QString attributeName;
356 bool attrIsX =
false;
357 bool attrIsY =
false;
358 bool attrIsZ =
false;
360 int attributeOffset = 0;
364 bool alreadyPrintedDebug =
false;
372 if ( symbol->
attribute() == QLatin1String(
"X" ) )
376 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
380 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
389 attributeType = attr->
type();
390 attributeName = attr->
name();
397 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
402 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
406 const char *ptr = block->
data();
413 for (
int i = 0; i < count; ++i )
418 const qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
419 const qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
420 const qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
422 double x = blockOffset.
x() + blockScale.
x() * ix;
423 double y = blockOffset.
y() + blockScale.
y() * iy;
424 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
431 if ( !alreadyPrintedDebug )
433 QgsDebugMsg( QStringLiteral(
"Error transforming point coordinate" ) );
434 alreadyPrintedDebug =
true;
438 point = context.map().mapToWorldCoordinates( point );
439 outNormal.positions.push_back( QVector3D( point.x(), point.y(), point.z() ) );
442 outNormal.parameter.push_back( x );
444 outNormal.parameter.push_back( y );
446 outNormal.parameter.push_back( z );
450 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
451 outNormal.parameter.push_back( iParam );
458 makeEntity( parent, context, outNormal,
false );
461 Qt3DRender::QGeometry *QgsColorRampPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
463 return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
466 QgsRGBPointCloud3DSymbolHandler::QgsRGBPointCloud3DSymbolHandler()
467 : QgsPointCloud3DSymbolHandler()
507 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
511 const char *ptr = block->
data();
520 bool alreadyPrintedDebug =
false;
533 for (
int i = 0; i < count; ++i )
538 const qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
539 const qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
540 const qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
541 double x = blockOffset.
x() + blockScale.
x() * ix;
542 double y = blockOffset.
y() + blockScale.
y() * iy;
543 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
550 if ( !alreadyPrintedDebug )
552 QgsDebugMsg( QStringLiteral(
"Error transforming point coordinate" ) );
553 alreadyPrintedDebug =
true;
557 const QgsVector3D p = context.map().mapToWorldCoordinates( point );
559 QVector3D color( 0.0f, 0.0f, 0.0f );
561 context.
getAttribute( ptr, i * recordSize + redOffset, redType, ir );
562 context.
getAttribute( ptr, i * recordSize + greenOffset, greenType, ig );
563 context.
getAttribute( ptr, i * recordSize + blueOffset, blueType, ib );
574 if ( useRedContrastEnhancement )
578 if ( useGreenContrastEnhancement )
582 if ( useBlueContrastEnhancement )
587 color.setX( ir / 255.0f );
588 color.setY( ig / 255.0f );
589 color.setZ( ib / 255.0f );
591 outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
592 outNormal.colors.push_back( color );
598 makeEntity( parent, context, outNormal,
false );
601 Qt3DRender::QGeometry *QgsRGBPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
603 return new QgsRGBPointCloud3DGeometry( parent, data, byteStride );
606 QgsClassificationPointCloud3DSymbolHandler::QgsClassificationPointCloud3DSymbolHandler()
607 : QgsPointCloud3DSymbolHandler()
621 const int xOffset = 0;
628 QString attributeName;
629 bool attrIsX =
false;
630 bool attrIsY =
false;
631 bool attrIsZ =
false;
633 int attributeOffset = 0;
640 if ( symbol->
attribute() == QLatin1String(
"X" ) )
644 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
648 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
657 attributeType = attr->
type();
658 attributeName = attr->
name();
665 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
670 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
674 const char *ptr = block->
data();
683 bool alreadyPrintedDebug =
false;
686 for (
int i = 0; i < count; ++i )
691 const qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
692 const qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
693 const qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
695 double x = blockOffset.
x() + blockScale.
x() * ix;
696 double y = blockOffset.
y() + blockScale.
y() * iy;
697 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
704 if ( !alreadyPrintedDebug )
706 QgsDebugMsg( QStringLiteral(
"Error transforming point coordinate" ) );
707 alreadyPrintedDebug =
true;
711 const QgsVector3D p = context.map().mapToWorldCoordinates( point );
720 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
722 if ( filteredOutValues.contains( (
int ) iParam ) )
724 outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
725 outNormal.parameter.push_back( iParam );
731 makeEntity( parent, context, outNormal,
false );
735 Qt3DRender::QGeometry *QgsClassificationPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
737 return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
Represents a indexed point cloud node in octree.
QString attribute() const
Returns the attribute used to select the color of the point cloud.
QString attribute() const
Returns the attribute used to select the color of the point cloud.
Manipulates raster or point cloud pixel values so that they enhanceContrast or clip into a specified ...
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
bool isValueInDisplayableRange(double value)
Returns true if a pixel value is in displayable range, false if pixel is outside of range (i....
int enhanceContrast(double value)
Applies the contrast enhancement to a value.
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
Custom exception class for Coordinate Reference System related exceptions.
void canceled()
Internal routines can connect to this signal if they use event loop.
Encapsulates the render context for a 3D point cloud rendering operation.
void getAttribute(const char *data, std::size_t offset, QgsPointCloudAttribute::DataType type, T &value) const
Retrieves the attribute value from data at the specified offset, where type indicates the original da...
QSet< int > getFilteredOutValues() const
Returns a set containing the filtered out values.
QgsFeedback * feedback() const
Returns the feedback object used to cancel rendering and check if rendering was canceled.
double zValueScale() const
Returns any constant scaling factor which must be applied to z values taken from the point cloud inde...
QgsPointCloudAttributeCollection attributes() const
Returns the attributes associated with the rendered block.
bool isCanceled() const
Returns true if the rendering is canceled.
QgsCoordinateTransform coordinateTransform() const
Returns the coordinate transform used to transform points from layer CRS to the map CRS.
QgsPointCloud3DSymbol * symbol() const
Returns the symbol used for rendering the point cloud.
double zValueFixedOffset() const
Returns any constant offset which must be applied to z values taken from the point cloud index.
virtual unsigned int byteStride()=0
Returns the byte stride for the geometries used to for the vertex buffer.
virtual void fillMaterial(Qt3DRender::QMaterial *material)=0SIP_SKIP
Used to fill material object with necessary QParameters (and consequently opengl uniforms)
float pointSize() const
Returns the point size of the point cloud.
Collection of point cloud attributes.
void push_back(const QgsPointCloudAttribute &attribute)
Adds extra attribute.
int pointRecordSize() const
Returns total size of record.
const QgsPointCloudAttribute * find(const QString &attributeName, int &offset) const
Finds the attribute with the name.
Attribute for point cloud data pair of name and size in bytes.
DataType
Systems of unit measurement.
QString name() const
Returns name of the attribute.
DataType type() const
Returns the data type.
Base class for handling loading QgsPointCloudBlock asynchronously.
QgsPointCloudBlock * block()
Returns the requested block.
void finished()
Emitted when the request processing has finished.
Base class for storing raw data from point cloud nodes.
QgsVector3D scale() const
Returns the custom scale of the block.
const char * data() const
Returns raw pointer to data.
int pointCount() const
Returns number of points that are stored in the block.
QgsVector3D offset() const
Returns the custom offset of the block.
Represents a indexed point clouds data in octree.
virtual QgsPointCloudBlock * nodeData(const IndexedPointCloudNode &n, const QgsPointCloudRequest &request)=0
Returns node data block.
virtual AccessType accessType() const =0
Returns the access type of the data If the access type is Remote, data will be fetched from an HTTP s...
virtual QgsPointCloudBlockRequest * asyncNodeData(const IndexedPointCloudNode &n, const QgsPointCloudRequest &request)=0
Returns a handle responsible for loading a node data block.
Point cloud data request.
void setAttributes(const QgsPointCloudAttributeCollection &attributes)
Set attributes filter in the request.
QString blueAttribute() const
Returns the attribute to use for the blue channel.
QString greenAttribute() const
Returns the attribute to use for the green channel.
QgsContrastEnhancement * blueContrastEnhancement()
Returns the contrast enhancement to use for the blue channel.
QString redAttribute() const
Returns the attribute to use for the red channel.
QgsContrastEnhancement * greenContrastEnhancement()
Returns the contrast enhancement to use for the green channel.
QgsContrastEnhancement * redContrastEnhancement()
Returns the contrast enhancement to use for the red channel.
double y() const
Returns Y coordinate.
double z() const
Returns Z coordinate.
double x() const
Returns X coordinate.