More class documentation

This commit is contained in:
Martin Dobias 2017-09-24 14:12:29 +02:00
parent d91ebe273b
commit 7389588745
15 changed files with 167 additions and 88 deletions

View File

@ -1,7 +1,7 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/./3d/qgsabstract3drenderer.h *
* src/core/3d/qgsabstract3drenderer.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@ -9,9 +9,6 @@
namespace Qt3DCore
{
}
class QgsAbstract3DRenderer
{
@ -62,7 +59,7 @@ Resolves references to other objects - second phase of loading - after readXml()
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/./3d/qgsabstract3drenderer.h *
* src/core/3d/qgsabstract3drenderer.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -22,7 +22,11 @@ class QgsProject;
class QDomElement;
//! Definition of the world
/** \ingroup 3d
* Definition of the world
*
* \since QGIS 3.0
*/
class _3D_EXPORT Qgs3DMapSettings : public QObject
{
Q_OBJECT
@ -31,42 +35,71 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
Qgs3DMapSettings( const Qgs3DMapSettings &other );
~Qgs3DMapSettings();
//! Reads configuration from a DOM element previously written by writeXml()
void readXml( const QDomElement &elem, const QgsReadWriteContext &context );
//! Writes configuration to a DOM element, to be used later with readXml()
QDomElement writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const;
//! Resolves references to other objects (map layers) after the call to readXml()
void resolveReferences( const QgsProject &project );
double originX, originY, originZ; //!< Coordinates in map CRS at which our 3D world has origin (0,0,0)
QgsCoordinateReferenceSystem crs; //!< Destination coordinate system of the world (TODO: not needed? can be
//! Sets background color of the 3D map view
void setBackgroundColor( const QColor &color );
//! Returns background color of the 3D map view
QColor backgroundColor() const;
//! Sets color used for selected features
void setSelectionColor( const QColor &color );
//! Returns color used for selected features
QColor selectionColor() const;
//
// terrain related config
//
//! Sets vertical scale (exaggeration) of terrain
//! (1 = true scale, > 1 = hills get more pronounced)
void setTerrainVerticalScale( double zScale );
//! Returns vertical scale (exaggeration) of terrain
double terrainVerticalScale() const;
//! Sets the list of map layers to be rendered as a texture of the terrain
void setLayers( const QList<QgsMapLayer *> &layers );
//! Returns the list of map layers to be rendered as a texture of the terrain
QList<QgsMapLayer *> layers() const;
//! Sets resolution (in pixels) of the texture of a terrain tile
//! \sa mapTileResolution()
void setMapTileResolution( int res );
//! Returns resolution (in pixels) of the texture of a terrain tile. This parameter influences
//! how many zoom levels for terrain tiles there will be (together with maxTerrainGroundError())
int mapTileResolution() const;
//! Sets maximum allowed screen error of terrain tiles in pixels.
//! \sa maxTerrainScreenError()
void setMaxTerrainScreenError( float error );
//! Returns maximum allowed screen error of terrain tiles in pixels. This parameter decides
//! how aggressively less detailed terrain tiles are swapped to more detailed ones as camera gets closer.
//! Each tile has its error defined in world units - this error gets projected to screen pixels
//! according to camera view and if the tile's error is greater than the allowed error, it will
//! be swapped by more detailed tiles with lower error.
float maxTerrainScreenError() const;
//! Returns maximum ground error of terrain tiles in world units.
//! \sa maxTerrainGroundError()
void setMaxTerrainGroundError( float error );
//! Returns maximum ground error of terrain tiles in world units. This parameter influences
//! how many zoom levels there will be (together with mapTileResolution()).
//! This value tells that when the given ground error is reached (e.g. 10 meters), it makes no sense
//! to further split terrain tiles into finer ones because they will not add extra details anymore.
float maxTerrainGroundError() const;
//! Sets terrain generator. It takes care of producing terrain tiles from the input data.
//! Takes ownership of the generator
void setTerrainGenerator( TerrainGenerator *gen );
//! Returns terrain generator. It takes care of producing terrain tiles from the input data.
TerrainGenerator *terrainGenerator() const { return mTerrainGenerator.get(); }
//
@ -79,21 +112,35 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
QString skyboxFileBase;
QString skyboxFileExtension;
//! Sets whether to display bounding boxes of terrain tiles (for debugging)
void setShowTerrainBoundingBoxes( bool enabled );
//! Returns whether to display bounding boxes of terrain tiles (for debugging)
bool showTerrainBoundingBoxes() const { return mShowTerrainBoundingBoxes; }
//! Sets whether to display extra tile info on top of terrain tiles (for debugging)
void setShowTerrainTilesInfo( bool enabled );
//! Returns whether to display extra tile info on top of terrain tiles (for debugging)
bool showTerrainTilesInfo() const { return mShowTerrainTileInfo; }
signals:
//! Emitted when the background color has changed
void backgroundColorChanged();
//! Emitted when the selection color has changed
void selectionColorChanged();
//! Emitted when the list of map layers for terrain texture has changed
void layersChanged();
//! Emitted when the terrain generator has changed
void terrainGeneratorChanged();
//! Emitted when the vertical scale of the terrain has changed
void terrainVerticalScaleChanged();
//! Emitted when the map tile resoulution has changed
void mapTileResolutionChanged();
//! Emitted when the maximum terrain screen error has changed
void maxTerrainScreenErrorChanged();
//! Emitted when the maximum terrain ground error has changed
void maxTerrainGroundErrorChanged();
//! Emitted when the flag whether terrain's bounding boxes are shown has changed
void showTerrainBoundingBoxesChanged();
//! Emitted when the flag whether terrain's tile info is shown has changed
void showTerrainTilesInfoChanged();
private:

View File

@ -20,7 +20,7 @@ QgsTessellatedPolygonGeometry::QgsTessellatedPolygonGeometry( QNode *parent )
m_vertexBuffer = new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer, this );
QgsTessellator tmpTess( 0, 0, m_withNormals );
const int stride = tmpTess.stride;
const int stride = tmpTess.stride();
m_positionAttribute = new Qt3DRender::QAttribute( this );
m_positionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
@ -73,8 +73,8 @@ void QgsTessellatedPolygonGeometry::setPolygons( const QList<QgsPolygonV2 *> &po
++i;
}
QByteArray data( ( const char * )tesselator.data.constData(), tesselator.data.count() * sizeof( float ) );
int nVerts = data.count() / tesselator.stride;
QByteArray data( ( const char * )tesselator.data().constData(), tesselator.data().count() * sizeof( float ) );
int nVerts = data.count() / tesselator.stride();
m_vertexBuffer->setData( data );
m_positionAttribute->setCount( nVerts );

View File

@ -10,14 +10,22 @@ namespace Qt3DRender
class QBuffer;
}
//! Class that represents polygons tessellated into 3D geometry
/** \ingroup 3d
* Class derived from Qt3DRender::QGeometry that represents polygons tessellated into 3D geometry.
*
* Takes a list of polygons as input, internally it does tessellation and writes output to the internal
* vertex buffer. Optionally it can add "walls" if the extrusion height is non-zero.
*
* \since QGIS 3.0
*/
class QgsTessellatedPolygonGeometry : public Qt3DRender::QGeometry
{
public:
//! Constructor
QgsTessellatedPolygonGeometry( QNode *parent = nullptr );
~QgsTessellatedPolygonGeometry();
// takes ownership of passed polygon geometries
//! Initializes vertex buffer from given polygons. Takes ownership of passed polygon geometries
void setPolygons( const QList<QgsPolygonV2 *> &polygons, const QgsPointXY &origin, float extrusionHeight );
private:

View File

@ -44,13 +44,13 @@ static void make_quad( float x0, float y0, float x1, float y1, float zLow, float
QgsTessellator::QgsTessellator( double originX, double originY, bool addNormals )
: originX( originX )
, originY( originY )
, addNormals( addNormals )
: mOriginX( originX )
, mOriginY( originY )
, mAddNormals( addNormals )
{
stride = 3 * sizeof( float );
mStride = 3 * sizeof( float );
if ( addNormals )
stride += 3 * sizeof( float );
mStride += 3 * sizeof( float );
}
@ -112,7 +112,7 @@ void QgsTessellator::addPolygon( const QgsPolygonV2 &polygon, float extrusionHei
exterior->pointAt( i, pt, vt );
if ( i == 0 || pt != ptPrev )
{
p2t::Point *pt2 = new p2t::Point( pt.x() - originX, pt.y() - originY );
p2t::Point *pt2 = new p2t::Point( pt.x() - mOriginX, pt.y() - mOriginY );
polyline.push_back( pt2 );
float zPt = qIsNaN( pt.z() ) ? 0 : pt.z();
z[pt2] = zPt;
@ -134,7 +134,7 @@ void QgsTessellator::addPolygon( const QgsPolygonV2 &polygon, float extrusionHei
hole->pointAt( j, pt, vt );
if ( j == 0 || pt != ptPrev )
{
p2t::Point *pt2 = new p2t::Point( pt.x() - originX, pt.y() - originY );
p2t::Point *pt2 = new p2t::Point( pt.x() - mOriginX, pt.y() - mOriginY );
holePolyline.push_back( pt2 );
float zPt = qIsNaN( pt.z() ) ? 0 : pt.z();
z[pt2] = zPt;
@ -158,9 +158,9 @@ void QgsTessellator::addPolygon( const QgsPolygonV2 &polygon, float extrusionHei
{
p2t::Point *p = t->GetPoint( j );
float zPt = z[p];
data << p->x << extrusionHeight + zPt << -p->y;
if ( addNormals )
data << 0.f << 1.f << 0.f;
mData << p->x << extrusionHeight + zPt << -p->y;
if ( mAddNormals )
mData << 0.f << 1.f << 0.f;
}
}
@ -171,9 +171,9 @@ void QgsTessellator::addPolygon( const QgsPolygonV2 &polygon, float extrusionHei
// add walls if extrusion is enabled
if ( extrusionHeight != 0 )
{
_makeWalls( *exterior, false, extrusionHeight, data, addNormals, originX, originY );
_makeWalls( *exterior, false, extrusionHeight, mData, mAddNormals, mOriginX, mOriginY );
for ( int i = 0; i < polygon.numInteriorRings(); ++i )
_makeWalls( *polygon.interiorRing( i ), true, extrusionHeight, data, addNormals, originX, originY );
_makeWalls( *polygon.interiorRing( i ), true, extrusionHeight, mData, mAddNormals, mOriginX, mOriginY );
}
}

View File

@ -5,25 +5,36 @@ class QgsPolygonV2;
#include <QVector>
/** \ingroup 3d
* Class that takes care of tessellation of polygons into triangles.
*
* It is expected that client code will create the tessellator object, then repeatedly call
* addPolygon() method that will generate triangles, and finally call data() to get final vertex data.
*
* Optionally provides extrusion by adding triangles that serve as walls when extrusion height is non-zero.
*
* \since QGIS 3.0
*/
class QgsTessellator
{
public:
//! Creates tessellator with a specified origin point of the world (in map coordinates)
QgsTessellator( double originX, double originY, bool addNormals );
//! Tessellates a triangle and adds its vertex entries to the output data array
void addPolygon( const QgsPolygonV2 &polygon, float extrusionHeight );
// input:
// - origin X/Y
// - whether to add walls
// - stream of geometries
// output:
// - vertex buffer data (+ index buffer data ?)
//! Returns array of triangle vertex data
QVector<float> data() const { return mData; }
//! Returns size of one vertex entry in bytes
int stride() const { return mStride; }
double originX, originY;
bool addNormals;
//QByteArray data;
QVector<float> data;
int stride; //!< Size of one vertex entry in bytes
private:
double mOriginX, mOriginY;
bool mAddNormals;
QVector<float> mData;
int mStride;
};
#endif // QGSTESSELLATOR_H

View File

@ -9,7 +9,7 @@
using namespace Qt3DRender;
QByteArray createPlaneVertexData( int res, const QByteArray &heights )
static QByteArray createPlaneVertexData( int res, const QByteArray &heights )
{
Q_ASSERT( res >= 2 );
Q_ASSERT( heights.count() == res * res * ( int )sizeof( float ) );
@ -67,7 +67,7 @@ QByteArray createPlaneVertexData( int res, const QByteArray &heights )
}
QByteArray createPlaneIndexData( int res )
static QByteArray createPlaneIndexData( int res )
{
QSize resolution( res, res );
// Create the index data. 2 triangles per rectangular face
@ -101,7 +101,10 @@ QByteArray createPlaneIndexData( int res )
return indexBytes;
}
///@cond PRIVATE
//! Generates vertex buffer for DEM terrain tiles
class PlaneVertexBufferFunctor : public QBufferDataGenerator
{
public:
@ -133,6 +136,8 @@ class PlaneVertexBufferFunctor : public QBufferDataGenerator
QByteArray m_heightMap;
};
//! Generates index buffer for DEM terrain tiles
class PlaneIndexBufferFunctor : public QBufferDataGenerator
{
public:
@ -161,6 +166,7 @@ class PlaneIndexBufferFunctor : public QBufferDataGenerator
int m_resolution;
};
/// @endcond

View File

@ -10,6 +10,11 @@
#include "chunkloader.h"
/** \ingroup 3d
* Terrain generator that creates a simple square flat area.
*
* \since QGIS 3.0
*/
class _3D_EXPORT FlatTerrainGenerator : public TerrainGenerator
{
public:
@ -24,9 +29,12 @@ class _3D_EXPORT FlatTerrainGenerator : public TerrainGenerator
virtual void writeXml( QDomElement &elem ) const override;
virtual void readXml( const QDomElement &elem ) override;
//! Sets extent of the terrain
void setExtent( const QgsRectangle &extent );
//! Sets CRS of the terrain
void setCrs( const QgsCoordinateReferenceSystem &crs );
//! Returns CRS of the terrain
QgsCoordinateReferenceSystem crs() const { return mCrs; }
private:

View File

@ -12,28 +12,35 @@ class QgsRasterLayer;
class Qgs3DMapSettings;
/**
* Responsible for:
* - rendering map tiles in background
* - caching tiles on disk (?)
/** \ingroup 3d
* Class responsible for rendering map images in background for the purposes of their use
* as textures for terrain's tiles.
*
* Tiles are asynchronously requested with render() call, when rendering is done the tileReady()
* signal will be emitted. Handles multiple rendering requests at a time - each request gets
* a unique job ID assigned.
*
* \since QGIS 3.0
*/
class MapTextureGenerator : public QObject
{
Q_OBJECT
public:
//! Initializes the object
MapTextureGenerator( const Qgs3DMapSettings &map );
//! Start async rendering of a map for the given extent (must be a square!)
//! Returns job ID
//! Starts async rendering of a map for the given extent (must be a square!).
//! Returns job ID. The class will emit tileReady() signal with the job ID when rendering is done.
int render( const QgsRectangle &extent, const QString &debugText = QString() );
//! Cancels a rendering job
void cancelJob( int jobId );
//! Render a map and return rendered image
//! Renders a map and returns rendered image. Blocks until the map rendering has finished
QImage renderSynchronously( const QgsRectangle &extent, const QString &debugText = QString() );
signals:
//! Signal emitted when rendering of a map tile has finished and passes the output image
void tileReady( int jobId, const QImage &image );
private slots:

View File

@ -4,6 +4,8 @@
#include "maptexturegenerator.h"
///@cond PRIVATE
class MapTextureImageDataGenerator : public Qt3DRender::QTextureImageDataGenerator
{
public:
@ -43,20 +45,10 @@ class MapTextureImageDataGenerator : public Qt3DRender::QTextureImageDataGenerat
QT3D_FUNCTOR( MapTextureImageDataGenerator )
};
/// @endcond
MapTextureImage::MapTextureImage( MapTextureGenerator *mapGen, const QgsRectangle &extent, const QString &debugText, Qt3DCore::QNode *parent )
: Qt3DRender::QAbstractTextureImage( parent )
, mapGen( mapGen )
, extent( extent )
, debugText( debugText )
, version( 1 )
, jobDone( false )
{
connect( mapGen, &MapTextureGenerator::tileReady, this, &MapTextureImage::onTileReady );
// request image
jobId = mapGen->render( extent, debugText );
}
////////
MapTextureImage::MapTextureImage( const QImage &image, const QgsRectangle &extent, const QString &debugText, Qt3DCore::QNode *parent )
@ -65,15 +57,12 @@ MapTextureImage::MapTextureImage( const QImage &image, const QgsRectangle &exten
, debugText( debugText )
, img( image )
, version( 1 )
, jobDone( true )
{
}
MapTextureImage::~MapTextureImage()
{
if ( !jobDone )
mapGen->cancelJob( jobId );
}
Qt3DRender::QTextureImageDataGeneratorPtr MapTextureImage::dataGenerator() const
@ -94,15 +83,3 @@ void MapTextureImage::setImage( const QImage &img )
version++;
notifyDataGeneratorChanged();
}
void MapTextureImage::onTileReady( int jobId, const QImage &img )
{
if ( jobId == this->jobId )
{
this->img = img;
this->jobDone = true;
version++;
notifyDataGeneratorChanged();
emit textureReady();
}
}

View File

@ -7,39 +7,39 @@
class MapTextureGenerator;
//! texture image with a rendered map
/** \ingroup 3d
* Class that stores an image with a rendered map. The image is used as a texture for one map tile.
*
* The texture is provided to Qt 3D through the implementation of dataGenerator() method.
*
* \since QGIS 3.0
*/
class MapTextureImage : public Qt3DRender::QAbstractTextureImage
{
Q_OBJECT
public:
//! constructor that will generate image asynchronously
MapTextureImage( MapTextureGenerator *mapGen, const QgsRectangle &extent, const QString &debugText = QString(), Qt3DCore::QNode *parent = nullptr );
//! constructor that uses already prepared image
//! Constructs the object with given image and map extent
MapTextureImage( const QImage &image, const QgsRectangle &extent, const QString &debugText, Qt3DCore::QNode *parent = nullptr );
~MapTextureImage();
virtual Qt3DRender::QTextureImageDataGeneratorPtr dataGenerator() const override;
//! Clears the current map image and emits signal that data generator has changed
void invalidate();
//! Stores a new map image and emits signal that data generator has changed
void setImage( const QImage &img );
//! Returns extent of the image in map coordinates
QgsRectangle imageExtent() const { return extent; }
//! Returns debug information (normally map tile coordinates)
QString imageDebugText() const { return debugText; }
private slots:
void onTileReady( int jobId, const QImage &img );
signals:
void textureReady();
private:
MapTextureGenerator *mapGen;
QgsRectangle extent;
QString debugText;
QImage img;
int version;
int jobId;
bool jobDone;
};
#endif // MAPTEXTUREIMAGE_H

View File

@ -136,7 +136,7 @@ TerrainMapUpdateJob::TerrainMapUpdateJob( MapTextureGenerator *mapTextureGenerat
{
TerrainChunkEntity *entity = qobject_cast<TerrainChunkEntity *>( node->entity );
connect( mapTextureGenerator, &MapTextureGenerator::tileReady, this, &TerrainMapUpdateJob::onTileReady );
mJobId = mapTextureGenerator->render( entity->mTextureImage->imageExtent(), entity->mTextureImage->imageDebugText() );
mJobId = mapTextureGenerator->render( entity->textureImage()->imageExtent(), entity->textureImage()->imageDebugText() );
}
void TerrainMapUpdateJob::cancel()
@ -151,7 +151,7 @@ void TerrainMapUpdateJob::onTileReady( int jobId, const QImage &image )
if ( mJobId == jobId )
{
TerrainChunkEntity *entity = qobject_cast<TerrainChunkEntity *>( node->entity );
entity->mTextureImage->setImage( image );
entity->textureImage()->setImage( image );
mJobId = -1;
emit finished();
}

View File

@ -53,8 +53,8 @@ void TerrainChunkLoader::loadTexture()
void TerrainChunkLoader::createTextureComponent( TerrainChunkEntity *entity )
{
Qt3DRender::QTexture2D *texture = new Qt3DRender::QTexture2D( entity );
entity->mTextureImage = new MapTextureImage( mTextureImage, mExtentMapCrs, mTileDebugText );
texture->addTextureImage( entity->mTextureImage );
MapTextureImage *textureImage = new MapTextureImage( mTextureImage, mExtentMapCrs, mTileDebugText );
texture->addTextureImage( textureImage );
texture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
texture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
Qt3DExtras::QTextureMaterial *material;
@ -67,6 +67,7 @@ void TerrainChunkLoader::createTextureComponent( TerrainChunkEntity *entity )
material->setShininess( 1 );
material->setAmbient( Qt::white );
#endif
entity->setTextureImage( textureImage );
entity->addComponent( material ); // takes ownership if the component has no parent
}

View File

@ -18,15 +18,30 @@ class QgsProject;
class MapTextureImage;
#include <Qt3DCore/QEntity>
/** \ingroup 3d
* Base class for 3D entities representing one tile of terrain.
* It contains pointer to tile's texture image.
*
* \since QGIS 3.0
*/
class TerrainChunkEntity : public Qt3DCore::QEntity
{
Q_OBJECT
public:
//! Constructs the entity, optionally with a parent that will own it
TerrainChunkEntity( Qt3DCore::QNode *parent = nullptr )
: Qt3DCore::QEntity( parent )
{
}
//! Assigns texture image. Should be called when the class is being initialized.
//! Texture image is owned by the texture used by the entity.
void setTextureImage( MapTextureImage *textureImage ) { mTextureImage = textureImage; }
//! Returns assigned texture image
MapTextureImage *textureImage() { return mTextureImage; }
private:
MapTextureImage *mTextureImage = nullptr;
};

View File

@ -11,10 +11,12 @@ class QgsProject;
class QgsReadWriteContext;
class Qgs3DMapSettings;
#ifndef SIP_RUN
namespace Qt3DCore
{
class QEntity;
}
#endif
/** \ingroup core
* Base class for all renderers that may to participate in 3D view.