25 #define GZIP_WINDOWS_BIT 15 + 16 26 #define GZIP_CHUNK_SIZE 32 * 1024 40 if ( input.isEmpty() )
49 strm.next_in = Z_NULL;
58 const char *input_data = input.constData();
59 int input_data_left = input.length();
68 if ( chunk_size <= 0 )
72 strm.next_in = (
unsigned char * )input_data;
73 strm.avail_in = chunk_size;
76 input_data += chunk_size;
77 input_data_left -= chunk_size;
87 strm.next_out = (
unsigned char * )out;
91 ret = inflate( &strm, Z_NO_FLUSH );
112 output.append( (
char * )out, have );
115 while ( strm.avail_out == 0 );
118 while ( ret != Z_STREAM_END );
124 return ( ret == Z_STREAM_END );
130 for (
int i = 0; i < count; ++i )
132 quint16 encoded = *( quint16 * ) dataPtr;
134 qint16 decoded = ( encoded >> 1 ) ^ ( -( encoded & 1 ) );
141 static QString _tileFilename(
int tx,
int ty,
int tz )
143 return QString(
"/tmp/terrain-%1-%2-%3" ).arg( tz ).arg( tx ).arg( ty );
148 QString filename = _tileFilename( tx, ty, tz );
150 if ( !f.open( QIODevice::ReadOnly ) )
157 if ( data.isEmpty() )
163 const char *dataPtr = data.constData();
178 quint32 vertexCount = *( quint32 * ) dataPtr;
180 t->
uvh.resize( 3 * vertexCount );
181 qint16 *vptr = t->
uvh.data();
184 qint16 u = 0, v = 0, h = 0;
185 for ( uint i = 0; i < vertexCount; ++i )
187 qint16 du = vptr[i], dv = vptr[vertexCount + i], dh = vptr[vertexCount * 2 + i];
192 vptr[vertexCount + i] = v;
193 vptr[vertexCount * 2 + i] = h;
196 Q_ASSERT( vertexCount < 65537 );
207 quint32 triangleCount = *( quint32 * ) dataPtr;
209 t->
indices.resize( 3 * triangleCount );
210 quint16 *indicesPtr = t->
indices.data();
211 quint16 *srcIdxPtr = ( quint16 * )dataPtr;
213 for ( uint i = 0; i < triangleCount * 3; ++i )
215 quint16 code = *srcIdxPtr++;
216 *indicesPtr++ = highest - code;
233 #include <QGuiApplication> 234 #include <QNetworkRequest> 235 #include <QNetworkReply> 242 QString tileFilename = _tileFilename( tx, ty, tz );
243 if ( !QFile::exists( tileFilename ) )
245 qDebug() <<
"downloading tile " << tx <<
" " << ty <<
" " << tz;
246 bool downloaded =
false;
247 QString url = QString(
"http://assets.agi.com/stk-terrain/tilesets/world/tiles/%1/%2/%3.terrain" ).arg( tz ).arg( tx ).arg( ty );
248 QNetworkRequest request( url );
249 request.setRawHeader( QByteArray(
"Accept-Encoding" ), QByteArray(
"gzip" ) );
250 request.setRawHeader( QByteArray(
"Accept" ), QByteArray(
"application/vnd.quantized-mesh,application/octet-stream;q=0.9" ) );
251 request.setRawHeader( QByteArray(
"User-Agent" ), QByteArray(
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/58.0.3029.110 Chrome/58.0.3029.110 Safari/537.36" ) );
253 connect( reply, &QNetworkReply::finished, [reply, tileFilename, &downloaded]
255 QFile fOut( tileFilename );
256 fOut.open( QIODevice::WriteOnly );
257 fOut.write( reply->readAll() );
259 reply->deleteLater();
263 while ( !downloaded )
265 qApp->processEvents();
277 : QGeometry( parent )
279 int vertexCount = t->
uvh.count() / 3;
280 int indexCount = t->
indices.count();
282 int vertexEntrySize =
sizeof( float ) * ( 3 + 2 );
291 const qint16 *uvh = t->
uvh.constData();
292 vb.resize( vertexCount * vertexEntrySize );
293 float *vbptr = (
float * ) vb.data();
294 for (
int i = 0; i < vertexCount; ++i )
296 qint16 u = uvh[i], v = uvh[vertexCount + i], h = uvh[vertexCount * 2 + i];
297 float uNorm = u / 32767.f;
298 float vNorm = v / 32767.f;
299 float hNorm = h / 32767.f;
300 float xWgs = xMinWgs + widthWgs * uNorm;
301 float yWgs = yMinWgs + heightWgs * vNorm;
305 QgsPointXY ptFinal( ptProjected.x() - ptMinProjected.
x(), ptProjected.y() - ptMinProjected.
y() );
308 *vbptr++ = ptFinal.
x();
310 *vbptr++ = -ptFinal.y();
319 ib.resize( indexCount * 2 );
320 memcpy( ib.data(), t->
indices.constData(), ib.count() );
333 m_vertexBuffer =
new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer,
this );
334 m_vertexBuffer->setData( vb );
336 m_indexBuffer =
new Qt3DRender::QBuffer( Qt3DRender::QBuffer::IndexBuffer,
this );
337 m_indexBuffer->setData( ib );
339 m_positionAttribute =
new Qt3DRender::QAttribute(
this );
340 m_positionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
341 #if QT_VERSION >= 0x050800 342 m_positionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
343 m_positionAttribute->setVertexSize( 3 );
345 m_positionAttribute->setDataType( Qt3DRender::QAttribute::Float );
346 m_positionAttribute->setDataSize( 3 );
348 m_positionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
349 m_positionAttribute->setBuffer( m_vertexBuffer );
350 m_positionAttribute->setByteStride( vertexEntrySize );
351 m_positionAttribute->setCount( vertexCount );
353 m_texCoordAttribute =
new Qt3DRender::QAttribute(
this );
354 m_texCoordAttribute->setName( Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName() );
355 #if QT_VERSION >= 0x050800 356 m_texCoordAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
357 m_texCoordAttribute->setVertexSize( 2 );
359 m_texCoordAttribute->setDataType( Qt3DRender::QAttribute::Float );
360 m_texCoordAttribute->setDataSize( 2 );
362 m_texCoordAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
363 m_texCoordAttribute->setBuffer( m_vertexBuffer );
364 m_texCoordAttribute->setByteStride( vertexEntrySize );
365 m_texCoordAttribute->setByteOffset( 3 *
sizeof(
float ) );
366 m_texCoordAttribute->setCount( vertexCount );
368 m_indexAttribute =
new Qt3DRender::QAttribute(
this );
369 m_indexAttribute->setAttributeType( Qt3DRender::QAttribute::IndexAttribute );
370 #if QT_VERSION >= 0x050800 371 m_indexAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedShort );
373 m_indexAttribute->setDataType( Qt3DRender::QAttribute::UnsignedShort );
375 m_indexAttribute->setBuffer( m_indexBuffer );
376 m_indexAttribute->setCount( indexCount );
378 addAttribute( m_positionAttribute );
379 addAttribute( m_texCoordAttribute );
380 addAttribute( m_indexAttribute );
A rectangle specified with double values.
static QuantizedMeshTile * readTile(int tx, int ty, int tz, const QgsRectangle &extent)
Reads a tile from a file in the local disk cache.
bool gzipDecompress(QByteArray input, QByteArray &output)
Decompresses the given buffer using the standard GZIP algorithm.
A class to represent a 2D point.
QuantizedMeshGeometry(QuantizedMeshTile *t, const Map3D &map, const QgsMapToPixel &mapToPixel, const QgsCoordinateTransform &terrainToMap, QNode *parent=nullptr)
Constructs geometry based on the loaded tile data.
Perform transforms between map coordinates and device coordinates.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
QuantizedMeshHeader header
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
const char * read_zigzag_encoded_int16_array(const char *dataPtr, int count, qint16 *out)
QVector< quint16 > indices
double width() const
Returns the width of the rectangle.
QgsPointXY transform(const QgsPointXY &p) const
Transform the point from map (world) coordinates to device coordinates.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
static void downloadTileIfMissing(int tx, int ty, int tz)
Downloads a tile to to a file in the local disk cache.
double height() const
Returns the height of the rectangle.