1818#include < Qt3DRender/qbuffer.h>
1919#include < Qt3DRender/qbufferdatagenerator.h>
2020#include < limits>
21+ #include < cmath>
2122
2223// /@cond PRIVATE
2324
@@ -51,6 +52,10 @@ static QByteArray createPlaneVertexData( int res, float skirtHeight, const QByte
5152 const float du = 1.0 / ( resolution.width () - 1 );
5253 const float dv = 1.0 / ( resolution.height () - 1 );
5354
55+ // the height of vertices with no-data value... the value should not really matter
56+ // as we do not create valid triangles that would use such vertices
57+ const float noDataHeight = 0 ;
58+
5459 // Iterate over z
5560 for ( int j = -1 ; j <= resolution.height (); ++j )
5661 {
@@ -71,6 +76,9 @@ static QByteArray createPlaneVertexData( int res, float skirtHeight, const QByte
7176 else
7277 height = zData[ jBound * resolution.width () + iBound ] - skirtHeight;
7378
79+ if ( std::isnan ( height ) )
80+ height = noDataHeight;
81+
7482 // position
7583 *fptr++ = x;
7684 *fptr++ = height;
@@ -91,8 +99,23 @@ static QByteArray createPlaneVertexData( int res, float skirtHeight, const QByte
9199 return bufferBytes;
92100}
93101
102+ inline int ijToHeightMapIndex ( int i, int j, int numVerticesX, int numVerticesZ )
103+ {
104+ i = qBound ( 1 , i, numVerticesX - 1 ) - 1 ;
105+ j = qBound ( 1 , j, numVerticesZ - 1 ) - 1 ;
106+ return j * ( numVerticesX - 2 ) + i;
107+ }
108+
109+
110+ static bool hasNoData ( int i, int j, const float *heightMap, int numVerticesX, int numVerticesZ )
111+ {
112+ return std::isnan ( heightMap[ ijToHeightMapIndex ( i, j, numVerticesX, numVerticesZ ) ] ) ||
113+ std::isnan ( heightMap[ ijToHeightMapIndex ( i + 1 , j, numVerticesX, numVerticesZ ) ] ) ||
114+ std::isnan ( heightMap[ ijToHeightMapIndex ( i, j + 1 , numVerticesX, numVerticesZ ) ] ) ||
115+ std::isnan ( heightMap[ ijToHeightMapIndex ( i + 1 , j + 1 , numVerticesX, numVerticesZ ) ] );
116+ }
94117
95- static QByteArray createPlaneIndexData ( int res )
118+ static QByteArray createPlaneIndexData ( int res, const QByteArray &heightMap )
96119{
97120 QSize resolution ( res, res );
98121 int numVerticesX = resolution.width () + 2 ;
@@ -106,6 +129,8 @@ static QByteArray createPlaneIndexData( int res )
106129 indexBytes.resize ( indices * sizeof ( quint32 ) );
107130 quint32 *indexPtr = reinterpret_cast <quint32 *>( indexBytes.data () );
108131
132+ const float *heightMapFloat = reinterpret_cast <const float *>( heightMap.constData () );
133+
109134 // Iterate over z
110135 for ( int j = 0 ; j < numVerticesZ - 1 ; ++j )
111136 {
@@ -115,6 +140,20 @@ static QByteArray createPlaneIndexData( int res )
115140 // Iterate over x
116141 for ( int i = 0 ; i < numVerticesX - 1 ; ++i )
117142 {
143+ if ( hasNoData ( i, j, heightMapFloat, numVerticesX, numVerticesZ ) )
144+ {
145+ // at least one corner of the quad has no-data value
146+ // so let's make two invalid triangles
147+ *indexPtr++ = rowStartIndex + i;
148+ *indexPtr++ = rowStartIndex + i;
149+ *indexPtr++ = rowStartIndex + i;
150+
151+ *indexPtr++ = rowStartIndex + i;
152+ *indexPtr++ = rowStartIndex + i;
153+ *indexPtr++ = rowStartIndex + i;
154+ continue ;
155+ }
156+
118157 // Split quad into two triangles
119158 *indexPtr++ = rowStartIndex + i;
120159 *indexPtr++ = nextRowStartIndex + i;
@@ -169,13 +208,14 @@ class PlaneVertexBufferFunctor : public QBufferDataGenerator
169208class PlaneIndexBufferFunctor : public QBufferDataGenerator
170209{
171210 public:
172- explicit PlaneIndexBufferFunctor ( int resolution )
211+ explicit PlaneIndexBufferFunctor ( int resolution, const QByteArray &heightMap )
173212 : mResolution( resolution )
213+ , mHeightMap( heightMap )
174214 {}
175215
176216 QByteArray operator ()() final
177217 {
178- return createPlaneIndexData ( mResolution );
218+ return createPlaneIndexData ( mResolution , mHeightMap );
179219 }
180220
181221 bool operator ==( const QBufferDataGenerator &other ) const final
@@ -190,6 +230,7 @@ class PlaneIndexBufferFunctor : public QBufferDataGenerator
190230
191231 private:
192232 int mResolution ;
233+ QByteArray mHeightMap ;
193234};
194235
195236
@@ -254,7 +295,7 @@ void DemTerrainTileGeometry::init()
254295 mIndexAttribute ->setCount ( faces * 3 );
255296
256297 mVertexBuffer ->setDataGenerator ( QSharedPointer<PlaneVertexBufferFunctor>::create ( mResolution , mSkirtHeight , mHeightMap ) );
257- mIndexBuffer ->setDataGenerator ( QSharedPointer<PlaneIndexBufferFunctor>::create ( mResolution ) );
298+ mIndexBuffer ->setDataGenerator ( QSharedPointer<PlaneIndexBufferFunctor>::create ( mResolution , mHeightMap ) );
258299
259300 addAttribute ( mPositionAttribute );
260301 addAttribute ( mTexCoordAttribute );
0 commit comments