1 /***************************************************************************
2 qgsmesh3dgeometry_p.cpp
3 -------------------------
4 begin : january 2020
5 copyright : (C) 2020 by Vincent Cloarec
6 email : vcloarec at gmail dot com
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "qgsmesh3dgeometry_p.h"
19
20 #include <Qt3DRender/qattribute.h>
21 #include <Qt3DRender/qbuffer.h>
22
23 #include <Qt3DRender/qbufferdatagenerator.h>
24 #include "qgsmeshlayer.h"
25 #include "qgstriangularmesh.h"
26 #include "qgsmeshlayerutils.h"
27
28
29 ///@cond PRIVATE
30
31 using namespace Qt3DRender;
32
createTerrainVertexData(const QgsTriangularMesh & mesh,const QgsVector3D & origin,float vertScale)33 static QByteArray createTerrainVertexData( const QgsTriangularMesh &mesh,
34 const QgsVector3D &origin,
35 float vertScale )
36 {
37 const int nVerts = mesh.vertices().count();
38
39 QVector<QVector3D> normals = mesh.vertexNormals( vertScale );
40
41 // Populate a buffer with the interleaved per-vertex data with
42 // vec3 pos, vec3 normal
43 const quint32 elementSize = 3 + 3;
44 const quint32 stride = elementSize * sizeof( float );
45 QByteArray bufferBytes;
46 bufferBytes.resize( stride * nVerts );
47
48 float *fptr = reinterpret_cast<float *>( bufferBytes.data() );
49
50 for ( int i = 0; i < nVerts; i++ )
51 {
52 const QgsMeshVertex &vert = mesh.vertices().at( i );
53 *fptr++ = float( vert.x() - origin.x() );
54 *fptr++ = float( vert.z() - origin.z() ) * vertScale ;
55 *fptr++ = float( -vert.y() + origin.y() );
56
57 QVector3D normal = normals.at( i );
58 normal = QVector3D( normal.x() * vertScale, -normal.y() * vertScale, normal.z() );
59 normal.normalized();
60
61 *fptr++ = normal.x();
62 *fptr++ = normal.z();
63 *fptr++ = normal.y();
64 }
65
66 return bufferBytes;
67 }
68
createDatasetVertexData(const QgsTriangularMesh & mesh,const QVector<double> verticalMagnitude,const QVector<double> scalarMagnitude,const QgsVector3D & origin,float vertScale,bool verticalRelative=false)69 static QByteArray createDatasetVertexData( const QgsTriangularMesh &mesh,
70 const QVector<double> verticalMagnitude,
71 const QVector<double> scalarMagnitude,
72 const QgsVector3D &origin,
73 float vertScale,
74 bool verticalRelative = false )
75 {
76 const int nVerts = mesh.vertices().count();
77
78 //Calculate normales with Z value equal to verticaleMagnitude
79 QVector<QVector3D> normals = QgsMeshLayerUtils::calculateNormals( mesh, verticalMagnitude, verticalRelative );
80
81 // Populate a buffer with the interleaved per-vertex data with
82 // vec3 pos, vec3 normal, float magnitude
83 const quint32 elementSize = 3 + 3 + 1 ;
84 const quint32 stride = elementSize * sizeof( float );
85 QByteArray bufferBytes;
86 bufferBytes.resize( stride * nVerts );
87
88 float *fptr = reinterpret_cast<float *>( bufferBytes.data() );
89
90 for ( int i = 0; i < nVerts; i++ )
91 {
92 const QgsMeshVertex &vert = mesh.vertices().at( i );
93 double vertMag = verticalMagnitude.at( i );
94 double scalarMag = scalarMagnitude.at( i );
95 if ( verticalRelative )
96 vertMag += vert.z();
97
98 *fptr++ = float( vert.x() - origin.x() );
99 *fptr++ = float( vertMag - origin.z() ) * vertScale ;
100 *fptr++ = float( -vert.y() + origin.y() );
101
102 QVector3D normal = normals.at( i );
103 normal = QVector3D( normal.x() * vertScale, -normal.y() * vertScale, normal.z() );
104 normal.normalized();
105
106 *fptr++ = normal.x();
107 *fptr++ = normal.z();
108 *fptr++ = normal.y();
109
110 *fptr++ = float( scalarMag );
111 }
112
113 return bufferBytes;
114 }
115
createIndexData(const QgsTriangularMesh & mesh)116 static QByteArray createIndexData( const QgsTriangularMesh &mesh )
117 {
118 const int faces = mesh.triangles().count();
119 const quint32 indices = static_cast<quint32>( 3 * faces );
120 Q_ASSERT( indices < std::numeric_limits<quint32>::max() );
121 QByteArray indexBytes;
122 indexBytes.resize( int( indices * sizeof( quint32 ) ) );
123 quint32 *indexPtr = reinterpret_cast<quint32 *>( indexBytes.data() );
124
125 for ( int i = 0; i < faces; ++i )
126 {
127 const QgsMeshFace &face = mesh.triangles().at( i );
128 for ( int i = 0; i < 3; ++i )
129 *indexPtr++ = quint32( face.at( i ) );
130 }
131
132 return indexBytes;
133 }
134
135
createDatasetIndexData(const QgsTriangularMesh & mesh,const QgsMeshDataBlock & mActiveFaceFlagValues,int activeFaceCount)136 static QByteArray createDatasetIndexData( const QgsTriangularMesh &mesh, const QgsMeshDataBlock &mActiveFaceFlagValues, int activeFaceCount )
137 {
138 const int trianglesCount = mesh.triangles().count();
139 const quint32 indices = static_cast<quint32>( 3 * activeFaceCount );
140 QByteArray indexBytes;
141 indexBytes.resize( int( indices * sizeof( quint32 ) ) );
142 quint32 *indexPtr = reinterpret_cast<quint32 *>( indexBytes.data() );
143
144 for ( int i = 0; i < trianglesCount; ++i )
145 {
146 int nativeFaceIndex = mesh.trianglesToNativeFaces()[i];
147 const bool isActive = mActiveFaceFlagValues.active().isEmpty() || mActiveFaceFlagValues.active( nativeFaceIndex );
148 if ( !isActive )
149 continue;
150 const QgsMeshFace &face = mesh.triangles().at( i );
151 for ( int i = 0; i < 3; ++i )
152 *indexPtr++ = quint32( face.at( i ) );
153 }
154
155 return indexBytes;
156 }
157
158 //! Generates vertex buffer for Mesh using vertex Z value as verticale magnitude
159 class MeshTerrainVertexBufferFunctor : public QBufferDataGenerator
160 {
161 public:
MeshTerrainVertexBufferFunctor(const QgsTriangularMesh & mesh,const QgsVector3D & origin,float vertScale)162 explicit MeshTerrainVertexBufferFunctor( const QgsTriangularMesh &mesh,
163 const QgsVector3D &origin,
164 float vertScale )
165 : mMesh( mesh ),
166 mOrigin( origin ),
167 mVertScale( vertScale )
168 {}
169
operator ()()170 QByteArray operator()() final
171 {
172 return createTerrainVertexData( mMesh, mOrigin, mVertScale );
173 }
174
operator ==(const QBufferDataGenerator & other) const175 bool operator ==( const QBufferDataGenerator &other ) const final
176 {
177 const MeshTerrainVertexBufferFunctor *otherFunctor = functor_cast<MeshTerrainVertexBufferFunctor>( &other );
178 if ( otherFunctor != nullptr )
179 return ( otherFunctor->mMesh.triangles().count() == mMesh.triangles().count() &&
180 abs( otherFunctor->mVertScale - mVertScale ) < std::numeric_limits<float>::min() );
181 return false;
182 }
183
184 QT3D_FUNCTOR( MeshTerrainVertexBufferFunctor )
185
186 private:
187
188 QgsTriangularMesh mMesh;
189 QgsVector3D mOrigin;
190 float mVertScale;
191
192 };
193
194 //! Generates index buffer for Mesh terrain
195 class MeshTerrainIndexBufferFunctor : public QBufferDataGenerator
196 {
197 public:
MeshTerrainIndexBufferFunctor(const QgsTriangularMesh & mesh)198 explicit MeshTerrainIndexBufferFunctor( const QgsTriangularMesh &mesh )
199 : mMesh( mesh )
200 {}
201
operator ()()202 QByteArray operator()() final
203 {
204 return createIndexData( mMesh );
205 }
206
operator ==(const QBufferDataGenerator & other) const207 bool operator ==( const QBufferDataGenerator &other ) const final
208 {
209 const MeshTerrainIndexBufferFunctor *otherFunctor = functor_cast<MeshTerrainIndexBufferFunctor>( &other );
210 if ( otherFunctor != nullptr )
211 return ( otherFunctor->mMesh.triangles().count() == mMesh.triangles().count() );
212 return false;
213 }
214
215 QT3D_FUNCTOR( MeshTerrainIndexBufferFunctor )
216
217 private:
218 QgsTriangularMesh mMesh;
219 };
220
221 //! Generates index buffer for Mesh dataset
222 class MeshDatasetIndexBufferFunctor : public QBufferDataGenerator
223 {
224 public:
MeshDatasetIndexBufferFunctor(const QgsTriangularMesh & mesh,const QgsMeshDataBlock & activeFace,int activeFaceCount)225 explicit MeshDatasetIndexBufferFunctor( const QgsTriangularMesh &mesh, const QgsMeshDataBlock &activeFace, int activeFaceCount )
226 : mMesh( mesh ), mActiveFace( activeFace ), mActiveFaceCount( activeFaceCount )
227 {}
228
operator ()()229 QByteArray operator()() final
230 {
231 return createDatasetIndexData( mMesh, mActiveFace, mActiveFaceCount );
232 }
233
operator ==(const QBufferDataGenerator & other) const234 bool operator ==( const QBufferDataGenerator &other ) const final
235 {
236 const MeshDatasetIndexBufferFunctor *otherFunctor = functor_cast<MeshDatasetIndexBufferFunctor>( &other );
237 if ( otherFunctor != nullptr )
238 return ( otherFunctor->mMesh.triangles().count() == mMesh.triangles().count() );
239 return false;
240 }
241
242 QT3D_FUNCTOR( MeshDatasetIndexBufferFunctor )
243 private:
244 QgsTriangularMesh mMesh;
245 QgsMeshDataBlock mActiveFace;
246 int mActiveFaceCount;
247
248 };
249
250 //! Generates vertex buffer for Mesh using dataset value as verticale magnitude and for color
251 class MeshDatasetVertexBufferFunctor : public QBufferDataGenerator
252 {
253 public:
254
255 /**
256 * verticalRelative parameter is TRUE when the vertical magnitude provides from the sum of the z vertices and the scalar dataset chosen
257 * for rendering the vertical component.
258 */
MeshDatasetVertexBufferFunctor(const QgsTriangularMesh & mesh,const QVector<double> verticaleMagnitude,const QVector<double> scalarMagnitude,const QgsVector3D & origin,float vertScale,bool verticalRelative=false)259 explicit MeshDatasetVertexBufferFunctor( const QgsTriangularMesh &mesh,
260 const QVector<double> verticaleMagnitude,
261 const QVector<double> scalarMagnitude,
262 const QgsVector3D &origin,
263 float vertScale,
264 bool verticalRelative = false )
265 : mMesh( mesh ),
266 mVerticaleMagnitude( verticaleMagnitude ),
267 mScalarMagnitude( scalarMagnitude ),
268 mOrigin( origin ),
269 mVertScale( vertScale ),
270 mVerticalRelative( verticalRelative )
271 {}
272
operator ()()273 QByteArray operator()() final
274 {
275 return createDatasetVertexData( mMesh,
276 mVerticaleMagnitude,
277 mScalarMagnitude,
278 mOrigin,
279 mVertScale,
280 mVerticalRelative );
281 }
282
operator ==(const QBufferDataGenerator & other) const283 bool operator ==( const QBufferDataGenerator &other ) const final
284 {
285 const MeshDatasetVertexBufferFunctor *otherFunctor = functor_cast<MeshDatasetVertexBufferFunctor>( &other );
286 if ( otherFunctor != nullptr )
287 return ( otherFunctor->mMesh.triangles().count() == mMesh.triangles().count() &&
288 otherFunctor->mVerticaleMagnitude.count() == mVerticaleMagnitude.count() &&
289 otherFunctor->mScalarMagnitude.count() == mScalarMagnitude.count() &&
290 abs( otherFunctor->mVertScale - mVertScale ) < std::numeric_limits<float>::min() &&
291 otherFunctor->mVerticalRelative == mVerticalRelative );
292 return false;
293 }
294
295 QT3D_FUNCTOR( MeshDatasetVertexBufferFunctor )
296
297 private:
298 QgsTriangularMesh mMesh;
299 QVector<double> mVerticaleMagnitude;
300 QVector<double> mScalarMagnitude;
301 QgsVector3D mOrigin;
302 float mVertScale;
303 bool mVerticalRelative = false;
304
305 };
306
QgsMesh3dGeometry(const QgsTriangularMesh & triangularMesh,const QgsVector3D & origin,const QgsMesh3DSymbol * symbol,Qt3DCore::QNode * parent)307 QgsMesh3dGeometry::QgsMesh3dGeometry( const QgsTriangularMesh &triangularMesh,
308 const QgsVector3D &origin,
309 const QgsMesh3DSymbol *symbol,
310 Qt3DCore::QNode *parent )
311 : Qt3DRender::QGeometry( parent )
312 , mOrigin( origin )
313 , mVertScale( symbol->verticalScale() )
314 , mTriangulaMesh( triangularMesh )
315 {}
316
QgsMeshDataset3dGeometry(const QgsTriangularMesh & triangularMesh,QgsMeshLayer * layer,const QgsDateTimeRange & timeRange,const QgsVector3D & origin,const QgsMesh3DSymbol * symbol,Qt3DCore::QNode * parent)317 QgsMeshDataset3dGeometry::QgsMeshDataset3dGeometry(
318 const QgsTriangularMesh &triangularMesh,
319 QgsMeshLayer *layer,
320 const QgsDateTimeRange &timeRange,
321 const QgsVector3D &origin,
322 const QgsMesh3DSymbol *symbol,
323 Qt3DCore::QNode *parent )
324 : QgsMesh3dGeometry( triangularMesh, origin, symbol, parent )
325 , mIsVerticalMagnitudeRelative( symbol->isVerticalMagnitudeRelative() )
326 , mVerticalGroupDatasetIndex( symbol->verticalDatasetGroupIndex() )
327 , mTimeRange( timeRange )
328 , mLayerRef( layer )
329 {
330 init();
331 }
332
init()333 void QgsMeshDataset3dGeometry::init()
334 {
335 if ( mVerticalGroupDatasetIndex < 0 )
336 return;
337
338 QVector<double> verticaleMagnitude;
339 QVector<double> scalarMagnitude;
340 QgsMeshDataBlock activeFaces;
341
342 int activefaceCount = extractDataset( verticaleMagnitude, scalarMagnitude, activeFaces );
343 if ( activefaceCount == 0 )
344 return;
345
346
347 if ( verticaleMagnitude.count() != mTriangulaMesh.vertices().count() ||
348 scalarMagnitude.count() != mTriangulaMesh.vertices().count() )
349 return;
350
351 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
352 Qt3DRender::QBuffer *vertexBuffer = new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer, this );
353 Qt3DRender::QBuffer *indexBuffer = new Qt3DRender::QBuffer( Qt3DRender::QBuffer::IndexBuffer, this );
354 #else
355 Qt3DRender::QBuffer *vertexBuffer = new Qt3DRender::QBuffer( this );
356 Qt3DRender::QBuffer *indexBuffer = new Qt3DRender::QBuffer( this );
357 #endif
358
359 const int stride = ( 3 /*position*/ +
360 3 /*normale*/ +
361 1 /*magnitude*/ ) * sizeof( float );
362
363 const uint nVerts = uint( mTriangulaMesh.vertices().count() );
364
365 prepareVerticesPositionAttribute( vertexBuffer, nVerts, stride, 0 );
366 prepareVerticesNormalAttribute( vertexBuffer, nVerts, stride, 3 );
367 prepareVerticesDatasetAttribute( vertexBuffer, nVerts, stride, 6 );
368
369 prepareIndexesAttribute( indexBuffer, activefaceCount );
370
371
372 Qt3DRender::QBufferDataGeneratorPtr vertexDataGenerator = Qt3DRender::QBufferDataGeneratorPtr(
373 new MeshDatasetVertexBufferFunctor( mTriangulaMesh, verticaleMagnitude, scalarMagnitude, mOrigin, mVertScale, mIsVerticalMagnitudeRelative ) );
374 vertexBuffer->setDataGenerator( vertexDataGenerator );
375
376 Qt3DRender::QBufferDataGeneratorPtr indexDataGenerator( new MeshDatasetIndexBufferFunctor(
377 mTriangulaMesh, activeFaces, activefaceCount ) );
378 indexBuffer->setDataGenerator( indexDataGenerator );
379 }
380
extractDataset(QVector<double> & verticalMagnitude,QVector<double> & scalarMagnitude,QgsMeshDataBlock & activeFaceFlagValues)381 int QgsMeshDataset3dGeometry::extractDataset( QVector<double> &verticalMagnitude, QVector<double> &scalarMagnitude, QgsMeshDataBlock &activeFaceFlagValues )
382 {
383 QgsMeshLayer *layer = meshLayer();
384
385 if ( !layer )
386 return 0;
387
388 QgsMeshDatasetIndex scalarDatasetIndex = layer->activeScalarDatasetAtTime( mTimeRange );
389
390 if ( !scalarDatasetIndex.isValid() )
391 return 0;
392
393 if ( mVerticalGroupDatasetIndex < 0 )
394 return 0;
395
396 const QgsMesh nativeMesh = *layer->nativeMesh();
397
398 //extract the scalar dataset used to render vertical magnitude of geometry
399 //define the vertical magnitude datasetIndex
400 QgsMeshDatasetIndex verticalMagDatasetIndex;
401 verticalMagDatasetIndex = layer->datasetIndexAtTime( mTimeRange, mVerticalGroupDatasetIndex );
402 if ( !verticalMagDatasetIndex.isValid() )
403 {
404 //if invalid (for example, static mode) use the scalar dataset index
405 int vertDataSetIndex = scalarDatasetIndex.dataset();
406 vertDataSetIndex = std::min( vertDataSetIndex, layer->datasetCount( mVerticalGroupDatasetIndex ) - 1 );
407 verticalMagDatasetIndex = QgsMeshDatasetIndex( mVerticalGroupDatasetIndex, vertDataSetIndex );
408 }
409 //define the active face for vertical magnitude, the inactive faces will not be rendered
410 // The active face flag values are defined based on the vertival magnitude dataset
411 activeFaceFlagValues = layer->areFacesActive( verticalMagDatasetIndex, 0, nativeMesh.faces.count() );
412 verticalMagnitude = QgsMeshLayerUtils::calculateMagnitudeOnVertices(
413 layer,
414 verticalMagDatasetIndex,
415 &activeFaceFlagValues );
416
417 //count active faces
418 int activeTriangularCount = 0;
419 if ( activeFaceFlagValues.active().isEmpty() )
420 activeTriangularCount = mTriangulaMesh.triangles().count();
421 else
422 for ( int i = 0; i < mTriangulaMesh.triangles().count(); ++i )
423 {
424 int nativeIndex = mTriangulaMesh.trianglesToNativeFaces()[i];
425 if ( activeFaceFlagValues.active( nativeIndex ) )
426 activeTriangularCount++;
427 }
428
429 //extract the scalar dataset used to render color shading
430 QgsMeshDataBlock scalarActiveFaceFlagValues =
431 layer->areFacesActive( scalarDatasetIndex, 0, nativeMesh.faces.count() );
432 scalarMagnitude = QgsMeshLayerUtils::calculateMagnitudeOnVertices(
433 layer,
434 scalarDatasetIndex,
435 &scalarActiveFaceFlagValues );
436
437 return activeTriangularCount;
438 }
439
440
QgsMeshTerrain3dGeometry(const QgsTriangularMesh & triangularMesh,const QgsVector3D & origin,const QgsMesh3DSymbol * symbol,Qt3DCore::QNode * parent)441 QgsMeshTerrain3dGeometry::QgsMeshTerrain3dGeometry(
442 const QgsTriangularMesh &triangularMesh,
443 const QgsVector3D &origin,
444 const QgsMesh3DSymbol *symbol,
445 Qt3DCore::QNode *parent )
446 : QgsMesh3dGeometry( triangularMesh, origin, symbol, parent )
447 {
448 init();
449 }
450
init()451 void QgsMeshTerrain3dGeometry::init()
452 {
453 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
454 Qt3DRender::QBuffer *vertexBuffer = new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer, this );
455 Qt3DRender::QBuffer *indexBuffer = new Qt3DRender::QBuffer( Qt3DRender::QBuffer::IndexBuffer, this );
456 #else
457 Qt3DRender::QBuffer *vertexBuffer = new Qt3DRender::QBuffer( this );
458 Qt3DRender::QBuffer *indexBuffer = new Qt3DRender::QBuffer( this );
459 #endif
460
461 const int stride = ( 3 /*position*/ +
462 3 /*normale*/ ) * sizeof( float );
463
464 const uint nVerts = uint( mTriangulaMesh.vertices().count() );
465
466 prepareVerticesPositionAttribute( vertexBuffer, nVerts, stride, 0 );
467 prepareVerticesNormalAttribute( vertexBuffer, nVerts, stride, 3 );
468 prepareIndexesAttribute( indexBuffer, mTriangulaMesh.triangles().count() );
469
470 Qt3DRender::QBufferDataGeneratorPtr vertexDataGenerator =
471 Qt3DRender::QBufferDataGeneratorPtr( new MeshTerrainVertexBufferFunctor( mTriangulaMesh, mOrigin, mVertScale ) );
472 vertexBuffer->setDataGenerator( vertexDataGenerator );
473
474 Qt3DRender::QBufferDataGeneratorPtr indexDataGenerator( new MeshTerrainIndexBufferFunctor( mTriangulaMesh ) );
475 indexBuffer->setDataGenerator( indexDataGenerator );
476
477 }
478
prepareVerticesPositionAttribute(Qt3DRender::QBuffer * buffer,int count,int stride,int offset)479 void QgsMesh3dGeometry::prepareVerticesPositionAttribute( Qt3DRender::QBuffer *buffer, int count, int stride, int offset )
480 {
481 Qt3DRender::QAttribute *positionAttribute = new QAttribute( this );
482
483 positionAttribute->setName( QAttribute::defaultPositionAttributeName() );
484 positionAttribute->setVertexBaseType( QAttribute::Float );
485 positionAttribute->setVertexSize( 3 );
486 positionAttribute->setAttributeType( QAttribute::VertexAttribute );
487 positionAttribute->setBuffer( buffer );
488 positionAttribute->setByteStride( stride );
489 positionAttribute->setByteOffset( offset * sizeof( float ) );
490 positionAttribute->setCount( count );
491
492 addAttribute( positionAttribute );
493 }
494
prepareVerticesNormalAttribute(Qt3DRender::QBuffer * buffer,int count,int stride,int offset)495 void QgsMesh3dGeometry::prepareVerticesNormalAttribute( Qt3DRender::QBuffer *buffer, int count, int stride, int offset )
496 {
497 Qt3DRender::QAttribute *normalAttribute = new QAttribute( this );
498
499 normalAttribute->setName( QAttribute::defaultNormalAttributeName() );
500 normalAttribute->setVertexBaseType( QAttribute::Float );
501 normalAttribute->setVertexSize( 3 );
502 normalAttribute->setAttributeType( QAttribute::VertexAttribute );
503 normalAttribute->setBuffer( buffer );
504 normalAttribute->setByteStride( stride );
505 normalAttribute->setByteOffset( offset * sizeof( float ) );
506 normalAttribute->setCount( count );
507
508 addAttribute( normalAttribute );
509 }
510
prepareVerticesDatasetAttribute(Qt3DRender::QBuffer * buffer,int count,int stride,int offset)511 void QgsMeshDataset3dGeometry::prepareVerticesDatasetAttribute( Qt3DRender::QBuffer *buffer, int count, int stride, int offset )
512 {
513 Qt3DRender::QAttribute *magnitudeAttribute = new QAttribute( this );
514
515 magnitudeAttribute->setName( "scalarMagnitude" );
516 magnitudeAttribute->setVertexBaseType( QAttribute::Float );
517 magnitudeAttribute->setVertexSize( 1 );
518 magnitudeAttribute->setAttributeType( QAttribute::VertexAttribute );
519 magnitudeAttribute->setBuffer( buffer );
520 magnitudeAttribute->setByteStride( stride );
521 magnitudeAttribute->setByteOffset( offset * sizeof( float ) );
522 magnitudeAttribute->setCount( count );
523
524 addAttribute( magnitudeAttribute );
525 }
526
meshLayer() const527 QgsMeshLayer *QgsMeshDataset3dGeometry::meshLayer() const
528 {
529 return qobject_cast<QgsMeshLayer *>( mLayerRef.layer.data() );
530 }
531
prepareIndexesAttribute(Qt3DRender::QBuffer * buffer,int trianglesCount)532 void QgsMesh3dGeometry::prepareIndexesAttribute( Qt3DRender::QBuffer *buffer, int trianglesCount )
533 {
534
535 Qt3DRender::QAttribute *indexAttribute = new QAttribute( this );
536 indexAttribute->setAttributeType( QAttribute::IndexAttribute );
537 indexAttribute->setVertexBaseType( QAttribute::UnsignedInt );
538 indexAttribute->setBuffer( buffer );
539
540 // Each primitive has 3 vertices
541 indexAttribute->setCount( trianglesCount * 3 );
542
543 addAttribute( indexAttribute );
544 }
545
546