29 #include <Qt3DRender/QGeometryRenderer>
30 #include <Qt3DRender/QAttribute>
31 #include <Qt3DRender/QTechnique>
32 #include <Qt3DRender/QShaderProgram>
33 #include <Qt3DRender/QGraphicsApiFilter>
34 #include <Qt3DRender/QEffect>
38 QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent,
unsigned int byteStride )
40 , mPositionAttribute( new
Qt3DRender::QAttribute( this ) )
41 , mParameterAttribute( new
Qt3DRender::QAttribute( this ) )
42 , mColorAttribute( new
Qt3DRender::QAttribute( this ) )
43 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
46 , mVertexBuffer( new
Qt3DRender::QBuffer( this ) )
48 , mByteStride( byteStride )
53 QgsSingleColorPointCloud3DGeometry::QgsSingleColorPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
54 : QgsPointCloud3DGeometry( parent, byteStride )
56 mPositionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
57 mPositionAttribute->setBuffer( mVertexBuffer );
58 mPositionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
59 mPositionAttribute->setVertexSize( 3 );
60 mPositionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
61 mPositionAttribute->setByteOffset( 0 );
62 mPositionAttribute->setByteStride( mByteStride );
63 addAttribute( mPositionAttribute );
64 makeVertexBuffer( data );
67 void QgsSingleColorPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
69 QByteArray vertexBufferData;
70 vertexBufferData.resize( data.positions.size() * mByteStride );
71 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
73 for (
int i = 0; i < data.positions.size(); ++i )
75 rawVertexArray[idx++] = data.positions.at( i ).x();
76 rawVertexArray[idx++] = data.positions.at( i ).y();
77 rawVertexArray[idx++] = data.positions.at( i ).z();
80 mVertexCount = data.positions.size();
81 mVertexBuffer->setData( vertexBufferData );
84 QgsColorRampPointCloud3DGeometry::QgsColorRampPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
85 : QgsPointCloud3DGeometry( parent, byteStride )
87 mPositionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
88 mPositionAttribute->setBuffer( mVertexBuffer );
89 mPositionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
90 mPositionAttribute->setVertexSize( 3 );
91 mPositionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
92 mPositionAttribute->setByteOffset( 0 );
93 mPositionAttribute->setByteStride( mByteStride );
94 addAttribute( mPositionAttribute );
95 mParameterAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
96 mParameterAttribute->setBuffer( mVertexBuffer );
97 mParameterAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
98 mParameterAttribute->setVertexSize( 1 );
99 mParameterAttribute->setName(
"vertexParameter" );
100 mParameterAttribute->setByteOffset( 12 );
101 mParameterAttribute->setByteStride( mByteStride );
102 addAttribute( mParameterAttribute );
103 makeVertexBuffer( data );
106 void QgsColorRampPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
108 QByteArray vertexBufferData;
109 vertexBufferData.resize( data.positions.size() * mByteStride );
110 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
112 Q_ASSERT( data.positions.size() == data.parameter.size() );
113 for (
int i = 0; i < data.positions.size(); ++i )
115 rawVertexArray[idx++] = data.positions.at( i ).x();
116 rawVertexArray[idx++] = data.positions.at( i ).y();
117 rawVertexArray[idx++] = data.positions.at( i ).z();
118 rawVertexArray[idx++] = data.parameter.at( i );
121 mVertexCount = data.positions.size();
122 mVertexBuffer->setData( vertexBufferData );
125 QgsRGBPointCloud3DGeometry::QgsRGBPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
126 : QgsPointCloud3DGeometry( parent, byteStride )
128 mPositionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
129 mPositionAttribute->setBuffer( mVertexBuffer );
130 mPositionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
131 mPositionAttribute->setVertexSize( 3 );
132 mPositionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
133 mPositionAttribute->setByteOffset( 0 );
134 mPositionAttribute->setByteStride( mByteStride );
135 addAttribute( mPositionAttribute );
136 mColorAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
137 mColorAttribute->setBuffer( mVertexBuffer );
138 mColorAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
139 mColorAttribute->setVertexSize( 3 );
140 mColorAttribute->setName( QStringLiteral(
"vertexColor" ) );
141 mColorAttribute->setByteOffset( 12 );
142 mColorAttribute->setByteStride( mByteStride );
143 addAttribute( mColorAttribute );
144 makeVertexBuffer( data );
147 void QgsRGBPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
149 QByteArray vertexBufferData;
150 vertexBufferData.resize( data.positions.size() * mByteStride );
151 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
153 Q_ASSERT( data.positions.size() == data.colors.size() );
154 for (
int i = 0; i < data.positions.size(); ++i )
156 rawVertexArray[idx++] = data.positions.at( i ).x();
157 rawVertexArray[idx++] = data.positions.at( i ).y();
158 rawVertexArray[idx++] = data.positions.at( i ).z();
159 rawVertexArray[idx++] = data.colors.at( i ).x();
160 rawVertexArray[idx++] = data.colors.at( i ).y();
161 rawVertexArray[idx++] = data.colors.at( i ).z();
163 mVertexCount = data.positions.size();
164 mVertexBuffer->setData( vertexBufferData );
167 QgsPointCloud3DSymbolHandler::QgsPointCloud3DSymbolHandler()
171 void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const QgsPointCloud3DRenderContext &context, QgsPointCloud3DSymbolHandler::PointData &out,
bool selected )
175 if ( out.positions.empty() )
179 Qt3DRender::QGeometry *geom = makeGeometry( parent, out, context.
symbol()->
byteStride() );
180 Qt3DRender::QGeometryRenderer *gr =
new Qt3DRender::QGeometryRenderer;
181 gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
182 gr->setVertexCount( out.positions.count() );
183 gr->setGeometry( geom );
186 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
189 Qt3DRender::QMaterial *mat =
new Qt3DRender::QMaterial;
193 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram( mat );
194 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/pointcloud.vert" ) ) ) );
195 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/pointcloud.frag" ) ) ) );
197 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass( mat );
198 renderPass->setShaderProgram( shaderProgram );
200 Qt3DRender::QPointSize *pointSize =
new Qt3DRender::QPointSize( renderPass );
201 pointSize->setSizeMode( Qt3DRender::QPointSize::Programmable );
203 renderPass->addRenderState( pointSize );
206 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
207 filterKey->setName( QStringLiteral(
"renderingStyle" ) );
208 filterKey->setValue(
"forward" );
210 Qt3DRender::QTechnique *technique =
new Qt3DRender::QTechnique;
211 technique->addRenderPass( renderPass );
212 technique->addFilterKey( filterKey );
213 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
214 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
215 technique->graphicsApiFilter()->setMajorVersion( 3 );
216 technique->graphicsApiFilter()->setMinorVersion( 1 );
218 Qt3DRender::QEffect *eff =
new Qt3DRender::QEffect;
219 eff->addTechnique( technique );
220 mat->setEffect( eff );
223 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
224 entity->addComponent( gr );
225 entity->addComponent( tr );
226 entity->addComponent( mat );
227 entity->setParent( parent );
232 QgsSingleColorPointCloud3DSymbolHandler::QgsSingleColorPointCloud3DSymbolHandler()
233 : QgsPointCloud3DSymbolHandler()
253 std::unique_ptr<QgsPointCloudBlock> block( pc->
nodeData( n, request ) );
257 const char *ptr = block->data();
258 int count = block->pointCount();
266 bool alreadyPrintedDebug =
false;
268 for (
int i = 0; i < count; ++i )
273 qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
274 qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
275 qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
277 double x = offset.
x() + scale.
x() * ix;
278 double y = offset.
y() + scale.
y() * iy;
279 double z = ( offset.
z() + scale.
z() * iz ) * zValueScale + zValueOffset;
286 if ( !alreadyPrintedDebug )
288 QgsDebugMsg( QStringLiteral(
"Error transforming point coordinate" ) );
289 alreadyPrintedDebug =
true;
294 outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
300 makeEntity( parent, context, outNormal,
false );
303 Qt3DRender::QGeometry *QgsSingleColorPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
305 return new QgsSingleColorPointCloud3DGeometry( parent, data, byteStride );
308 QgsColorRampPointCloud3DSymbolHandler::QgsColorRampPointCloud3DSymbolHandler()
309 : QgsPointCloud3DSymbolHandler()
323 const int xOffset = 0;
330 QString attributeName;
331 bool attrIsX =
false;
332 bool attrIsY =
false;
333 bool attrIsZ =
false;
335 int attributeOffset = 0;
339 bool alreadyPrintedDebug =
false;
347 if ( symbol->
attribute() == QLatin1String(
"X" ) )
351 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
355 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
364 attributeType = attr->
type();
365 attributeName = attr->
name();
372 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
377 std::unique_ptr<QgsPointCloudBlock> block( pc->
nodeData( n, request ) );
381 const char *ptr = block->data();
382 int count = block->pointCount();
388 for (
int i = 0; i < count; ++i )
393 qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
394 qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
395 qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
397 double x = offset.
x() + scale.
x() * ix;
398 double y = offset.
y() + scale.
y() * iy;
399 double z = ( offset.
z() + scale.
z() * iz ) * zValueScale + zValueOffset;
406 if ( !alreadyPrintedDebug )
408 QgsDebugMsg( QStringLiteral(
"Error transforming point coordinate" ) );
409 alreadyPrintedDebug =
true;
413 point = context.map().mapToWorldCoordinates( point );
414 outNormal.positions.push_back( QVector3D( point.x(), point.y(), point.z() ) );
417 outNormal.parameter.push_back( x );
419 outNormal.parameter.push_back( y );
421 outNormal.parameter.push_back( z );
425 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
426 outNormal.parameter.push_back( iParam );
433 makeEntity( parent, context, outNormal,
false );
436 Qt3DRender::QGeometry *QgsColorRampPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
438 return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
441 QgsRGBPointCloud3DSymbolHandler::QgsRGBPointCloud3DSymbolHandler()
442 : QgsPointCloud3DSymbolHandler()
482 std::unique_ptr<QgsPointCloudBlock> block( pc->
nodeData( n, request ) );
486 const char *ptr = block->data();
487 int count = block->pointCount();
495 bool alreadyPrintedDebug =
false;
508 for (
int i = 0; i < count; ++i )
513 qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
514 qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
515 qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
516 double x = offset.
x() + scale.
x() * ix;
517 double y = offset.
y() + scale.
y() * iy;
518 double z = ( offset.
z() + scale.
z() * iz ) * zValueScale + zValueOffset;
525 if ( !alreadyPrintedDebug )
527 QgsDebugMsg( QStringLiteral(
"Error transforming point coordinate" ) );
528 alreadyPrintedDebug =
true;
532 QgsVector3D p = context.map().mapToWorldCoordinates( point );
534 QVector3D color( 0.0f, 0.0f, 0.0f );
536 context.
getAttribute( ptr, i * recordSize + redOffset, redType, ir );
537 context.
getAttribute( ptr, i * recordSize + greenOffset, greenType, ig );
538 context.
getAttribute( ptr, i * recordSize + blueOffset, blueType, ib );
549 if ( useRedContrastEnhancement )
553 if ( useGreenContrastEnhancement )
557 if ( useBlueContrastEnhancement )
562 color.setX( ir / 255.0f );
563 color.setY( ig / 255.0f );
564 color.setZ( ib / 255.0f );
566 outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
567 outNormal.colors.push_back( color );
573 makeEntity( parent, context, outNormal,
false );
576 Qt3DRender::QGeometry *QgsRGBPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
578 return new QgsRGBPointCloud3DGeometry( parent, data, byteStride );
581 QgsClassificationPointCloud3DSymbolHandler::QgsClassificationPointCloud3DSymbolHandler()
582 : QgsPointCloud3DSymbolHandler()
596 const int xOffset = 0;
603 QString attributeName;
604 bool attrIsX =
false;
605 bool attrIsY =
false;
606 bool attrIsZ =
false;
608 int attributeOffset = 0;
615 if ( symbol->
attribute() == QLatin1String(
"X" ) )
619 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
623 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
632 attributeType = attr->
type();
633 attributeName = attr->
name();
640 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
645 std::unique_ptr<QgsPointCloudBlock> block( pc->
nodeData( n, request ) );
649 const char *ptr = block->data();
650 int count = block->pointCount();
658 bool alreadyPrintedDebug =
false;
661 for (
int i = 0; i < count; ++i )
666 qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
667 qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
668 qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
670 double x = offset.
x() + scale.
x() * ix;
671 double y = offset.
y() + scale.
y() * iy;
672 double z = ( offset.
z() + scale.
z() * iz ) * zValueScale + zValueOffset;
679 if ( !alreadyPrintedDebug )
681 QgsDebugMsg( QStringLiteral(
"Error transforming point coordinate" ) );
682 alreadyPrintedDebug =
true;
686 QgsVector3D p = context.map().mapToWorldCoordinates( point );
695 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
697 if ( filteredOutValues.contains( (
int ) iParam ) )
699 outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
700 outNormal.parameter.push_back( iParam );
706 makeEntity( parent, context, outNormal,
false );
710 Qt3DRender::QGeometry *QgsClassificationPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
712 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.
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.
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.
Represents a indexed point clouds data in octree.
QgsVector3D offset() const
Returns offset.
QgsVector3D scale() const
Returns scale.
virtual QgsPointCloudBlock * nodeData(const IndexedPointCloudNode &n, const QgsPointCloudRequest &request)=0
Returns 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.