17 #include <Qt3DRender/qattribute.h> 18 #include <Qt3DRender/qbuffer.h> 19 #include <Qt3DRender/qbufferdatagenerator.h> 28 static QByteArray createPlaneVertexData(
int res,
float skirtHeight,
const QByteArray &heights )
31 Q_ASSERT( heights.count() == res * res * ( int )
sizeof(
float ) );
33 const float *zData = (
const float * ) heights.constData();
34 const float *zBits = zData;
36 const int nVerts = ( res + 2 ) * ( res + 2 );
40 const quint32 elementSize = 3 + 2 + 3;
41 const quint32 stride = elementSize *
sizeof( float );
42 QByteArray bufferBytes;
43 bufferBytes.resize( stride * nVerts );
44 float *fptr =
reinterpret_cast<float *
>( bufferBytes.data() );
47 QSize resolution( res, res );
48 const float x0 = -w / 2.0f;
49 const float z0 = -h / 2.0f;
50 const float dx = w / ( resolution.width() - 1 );
51 const float dz = h / ( resolution.height() - 1 );
52 const float du = 1.0 / ( resolution.width() - 1 );
53 const float dv = 1.0 / ( resolution.height() - 1 );
57 const float noDataHeight = 0;
60 for (
int j = -1; j <= resolution.height(); ++j )
62 int jBound = qBound( 0, j, resolution.height() - 1 );
63 const float z = z0 +
static_cast<float>( jBound ) * dz;
64 const float v =
static_cast<float>( jBound ) * dv;
67 for (
int i = -1; i <= resolution.width(); ++i )
69 int iBound = qBound( 0, i, resolution.width() - 1 );
70 const float x = x0 +
static_cast<float>( iBound ) * dx;
71 const float u =
static_cast<float>( iBound ) * du;
74 if ( i == iBound && j == jBound )
77 height = zData[ jBound * resolution.width() + iBound ] - skirtHeight;
79 if ( std::isnan( height ) )
80 height = noDataHeight;
102 inline int ijToHeightMapIndex(
int i,
int j,
int numVerticesX,
int numVerticesZ )
104 i = qBound( 1, i, numVerticesX - 1 ) - 1;
105 j = qBound( 1, j, numVerticesZ - 1 ) - 1;
106 return j * ( numVerticesX - 2 ) + i;
110 static bool hasNoData(
int i,
int j,
const float *heightMap,
int numVerticesX,
int numVerticesZ )
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 ) ] );
118 static QByteArray createPlaneIndexData(
int res,
const QByteArray &heightMap )
120 QSize resolution( res, res );
121 int numVerticesX = resolution.width() + 2;
122 int numVerticesZ = resolution.height() + 2;
125 const int faces = 2 * ( numVerticesX - 1 ) * ( numVerticesZ - 1 );
126 const quint32 indices = 3 * faces;
127 Q_ASSERT( indices < std::numeric_limits<quint32>::max() );
128 QByteArray indexBytes;
129 indexBytes.resize( indices *
sizeof( quint32 ) );
130 quint32 *indexPtr =
reinterpret_cast<quint32 *
>( indexBytes.data() );
132 const float *heightMapFloat =
reinterpret_cast<const float *
>( heightMap.constData() );
135 for (
int j = 0; j < numVerticesZ - 1; ++j )
137 const int rowStartIndex = j * numVerticesX;
138 const int nextRowStartIndex = ( j + 1 ) * numVerticesX;
141 for (
int i = 0; i < numVerticesX - 1; ++i )
143 if ( hasNoData( i, j, heightMapFloat, numVerticesX, numVerticesZ ) )
147 *indexPtr++ = rowStartIndex + i;
148 *indexPtr++ = rowStartIndex + i;
149 *indexPtr++ = rowStartIndex + i;
151 *indexPtr++ = rowStartIndex + i;
152 *indexPtr++ = rowStartIndex + i;
153 *indexPtr++ = rowStartIndex + i;
158 *indexPtr++ = rowStartIndex + i;
159 *indexPtr++ = nextRowStartIndex + i;
160 *indexPtr++ = rowStartIndex + i + 1;
162 *indexPtr++ = nextRowStartIndex + i;
163 *indexPtr++ = nextRowStartIndex + i + 1;
164 *indexPtr++ = rowStartIndex + i + 1;
174 class PlaneVertexBufferFunctor :
public QBufferDataGenerator
177 explicit PlaneVertexBufferFunctor(
int resolution,
float skirtHeight,
const QByteArray &heightMap )
178 : mResolution( resolution )
179 , mSkirtHeight( skirtHeight )
180 , mHeightMap( heightMap )
183 QByteArray operator()() final
185 return createPlaneVertexData( mResolution, mSkirtHeight, mHeightMap );
188 bool operator ==(
const QBufferDataGenerator &other )
const final 190 const PlaneVertexBufferFunctor *otherFunctor = functor_cast<PlaneVertexBufferFunctor>( &other );
191 if ( otherFunctor !=
nullptr )
192 return ( otherFunctor->mResolution == mResolution &&
193 otherFunctor->mSkirtHeight == mSkirtHeight &&
194 otherFunctor->mHeightMap == mHeightMap );
198 QT3D_FUNCTOR( PlaneVertexBufferFunctor )
203 QByteArray mHeightMap;
208 class PlaneIndexBufferFunctor :
public QBufferDataGenerator
211 explicit PlaneIndexBufferFunctor(
int resolution,
const QByteArray &heightMap )
212 : mResolution( resolution )
213 , mHeightMap( heightMap )
216 QByteArray operator()() final
218 return createPlaneIndexData( mResolution, mHeightMap );
221 bool operator ==(
const QBufferDataGenerator &other )
const final 223 const PlaneIndexBufferFunctor *otherFunctor = functor_cast<PlaneIndexBufferFunctor>( &other );
224 if ( otherFunctor !=
nullptr )
225 return ( otherFunctor->mResolution == mResolution );
229 QT3D_FUNCTOR( PlaneIndexBufferFunctor )
233 QByteArray mHeightMap;
240 DemTerrainTileGeometry::DemTerrainTileGeometry(
int resolution,
float skirtHeight,
const QByteArray &heightMap, DemTerrainTileGeometry::QNode *parent )
241 : QGeometry( parent )
242 , mResolution( resolution )
243 , mSkirtHeight( skirtHeight )
244 , mHeightMap( heightMap )
249 void DemTerrainTileGeometry::init()
251 mPositionAttribute =
new QAttribute(
this );
252 mNormalAttribute =
new QAttribute(
this );
253 mTexCoordAttribute =
new QAttribute(
this );
254 mIndexAttribute =
new QAttribute(
this );
255 mVertexBuffer =
new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer,
this );
256 mIndexBuffer =
new Qt3DRender::QBuffer( Qt3DRender::QBuffer::IndexBuffer,
this );
258 int nVertsX = mResolution + 2;
259 int nVertsZ = mResolution + 2;
260 const int nVerts = nVertsX * nVertsZ;
261 const int stride = ( 3 + 2 + 3 ) *
sizeof(
float );
262 const int faces = 2 * ( nVertsX - 1 ) * ( nVertsZ - 1 );
264 mPositionAttribute->setName( QAttribute::defaultPositionAttributeName() );
265 mPositionAttribute->setVertexBaseType( QAttribute::Float );
266 mPositionAttribute->setVertexSize( 3 );
267 mPositionAttribute->setAttributeType( QAttribute::VertexAttribute );
268 mPositionAttribute->setBuffer( mVertexBuffer );
269 mPositionAttribute->setByteStride( stride );
270 mPositionAttribute->setCount( nVerts );
272 mTexCoordAttribute->setName( QAttribute::defaultTextureCoordinateAttributeName() );
273 mTexCoordAttribute->setVertexBaseType( QAttribute::Float );
274 mTexCoordAttribute->setVertexSize( 2 );
275 mTexCoordAttribute->setAttributeType( QAttribute::VertexAttribute );
276 mTexCoordAttribute->setBuffer( mVertexBuffer );
277 mTexCoordAttribute->setByteStride( stride );
278 mTexCoordAttribute->setByteOffset( 3 *
sizeof(
float ) );
279 mTexCoordAttribute->setCount( nVerts );
281 mNormalAttribute->setName( QAttribute::defaultNormalAttributeName() );
282 mNormalAttribute->setVertexBaseType( QAttribute::Float );
283 mNormalAttribute->setVertexSize( 3 );
284 mNormalAttribute->setAttributeType( QAttribute::VertexAttribute );
285 mNormalAttribute->setBuffer( mVertexBuffer );
286 mNormalAttribute->setByteStride( stride );
287 mNormalAttribute->setByteOffset( 5 *
sizeof(
float ) );
288 mNormalAttribute->setCount( nVerts );
290 mIndexAttribute->setAttributeType( QAttribute::IndexAttribute );
291 mIndexAttribute->setVertexBaseType( QAttribute::UnsignedInt );
292 mIndexAttribute->setBuffer( mIndexBuffer );
295 mIndexAttribute->setCount( faces * 3 );
297 mVertexBuffer->setDataGenerator( QSharedPointer<PlaneVertexBufferFunctor>::create( mResolution, mSkirtHeight, mHeightMap ) );
298 mIndexBuffer->setDataGenerator( QSharedPointer<PlaneIndexBufferFunctor>::create( mResolution, mHeightMap ) );
300 addAttribute( mPositionAttribute );
301 addAttribute( mTexCoordAttribute );
302 addAttribute( mNormalAttribute );
303 addAttribute( mIndexAttribute );
bool operator==(const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2)