Skip to content
Permalink
Browse files

Signals/slots in Map3D + partial scene udates from Map3D signals

  • Loading branch information
wonder-sk committed Sep 15, 2017
1 parent 9e0bf1d commit 3d9d455ebeabcf59553f72fd3db9e916ecb7ae38
@@ -39,6 +39,7 @@ SET(QGIS_3D_SRCS

SET(QGIS_3D_MOC_HDRS
cameracontroller.h
map3d.h
scene.h

chunks/chunkedentity.h
@@ -48,6 +49,7 @@ SET(QGIS_3D_MOC_HDRS
terrain/maptexturegenerator.h
terrain/maptextureimage.h
terrain/terrain.h
terrain/terraingenerator.h
)

QT5_WRAP_CPP(QGIS_3D_MOC_SRCS ${QGIS_3D_MOC_HDRS})
@@ -6,7 +6,6 @@

CameraController::CameraController( Qt3DCore::QNode *parent )
: Qt3DCore::QEntity( parent )
, mTerrainPicker( nullptr )
, mLastPressedHeight( 0 )
, mMouseDevice( new Qt3DInput::QMouseDevice() )
, mKeyboardDevice( new Qt3DInput::QKeyboardDevice() )
@@ -26,10 +25,6 @@ CameraController::CameraController( Qt3DCore::QNode *parent )
, mKeyboardTyNegInput( new Qt3DInput::QButtonAxisInput() )
{

// object picker for terrain for correct map panning. it will be associated as a component of terrain entity
mTerrainPicker = new Qt3DRender::QObjectPicker;
connect( mTerrainPicker, &Qt3DRender::QObjectPicker::pressed, this, &CameraController::onPickerMousePressed );

// not using QAxis + QAnalogAxisInput for mouse X,Y because
// it is only in action when a mouse button is pressed.
mMouseHandler->setSourceDevice( mMouseDevice );
@@ -95,6 +90,12 @@ CameraController::CameraController( Qt3DCore::QNode *parent )
addComponent( mLogicalDevice );
}

void CameraController::addTerrainPicker( Qt3DRender::QObjectPicker *picker )
{
// object picker for terrain for correct map panning
connect( picker, &Qt3DRender::QObjectPicker::pressed, this, &CameraController::onPickerMousePressed );
}

void CameraController::setCamera( Qt3DRender::QCamera *camera )
{
if ( mCamera == camera )
@@ -18,7 +18,8 @@ class _3D_EXPORT CameraController : public Qt3DCore::QEntity

Qt3DRender::QCamera *camera() const { return mCamera; }
QRect viewport() const { return mViewport; }
Qt3DRender::QObjectPicker *terrainPicker() const { return mTerrainPicker; }

void addTerrainPicker( Qt3DRender::QObjectPicker *picker );

void setCamera( Qt3DRender::QCamera *camera );
void setViewport( const QRect &viewport );
@@ -43,8 +44,6 @@ class _3D_EXPORT CameraController : public Qt3DCore::QEntity
Qt3DRender::QCamera *mCamera;
//! used for computation of translation when dragging mouse
QRect mViewport;
//! picker of terrain to know height of terrain when dragging
Qt3DRender::QObjectPicker *mTerrainPicker;
//! height of terrain when mouse button was last pressed - for camera control
float mLastPressedHeight;

@@ -81,29 +81,30 @@ Map3D::Map3D()
, tileTextureSize( 512 )
, maxTerrainError( 3.f )
, skybox( false )
, showBoundingBoxes( false )
, drawTerrainTileInfo( false )
, mShowTerrainBoundingBoxes( false )
, mShowTerrainTileInfo( false )
{
}

Map3D::Map3D( const Map3D &other )
: originX( other.originX )
: QObject()
, originX( other.originX )
, originY( other.originY )
, originZ( other.originZ )
, crs( other.crs )
, backgroundColor( other.backgroundColor )
, zExaggeration( other.zExaggeration )
, tileTextureSize( other.tileTextureSize )
, maxTerrainError( other.maxTerrainError )
, terrainGenerator( other.terrainGenerator ? other.terrainGenerator->clone() : nullptr )
, mTerrainGenerator( other.mTerrainGenerator ? other.mTerrainGenerator->clone() : nullptr )
, polygonRenderers( other.polygonRenderers )
, pointRenderers( other.pointRenderers )
, lineRenderers( other.lineRenderers )
, skybox( other.skybox )
, skyboxFileBase( other.skyboxFileBase )
, skyboxFileExtension( other.skyboxFileExtension )
, showBoundingBoxes( other.showBoundingBoxes )
, drawTerrainTileInfo( other.drawTerrainTileInfo )
, mShowTerrainBoundingBoxes( other.mShowTerrainBoundingBoxes )
, mShowTerrainTileInfo( other.mShowTerrainTileInfo )
, mLayers( other.mLayers )
{
}
@@ -141,7 +142,7 @@ void Map3D::readXml( const QDomElement &elem, const QgsReadWriteContext &context
QString terrainGenType = elemTerrainGenerator.attribute( "type" );
if ( terrainGenType == "dem" )
{
terrainGenerator.reset( new DemTerrainGenerator );
mTerrainGenerator.reset( new DemTerrainGenerator );
}
else if ( terrainGenType == "quantized-mesh" )
{
@@ -154,9 +155,9 @@ void Map3D::readXml( const QDomElement &elem, const QgsReadWriteContext &context
{
FlatTerrainGenerator *flatGen = new FlatTerrainGenerator;
flatGen->setCrs( crs );
terrainGenerator.reset( flatGen );
mTerrainGenerator.reset( flatGen );
}
terrainGenerator->readXml( elemTerrainGenerator );
mTerrainGenerator->readXml( elemTerrainGenerator );

polygonRenderers.clear();
pointRenderers.clear();
@@ -193,8 +194,8 @@ void Map3D::readXml( const QDomElement &elem, const QgsReadWriteContext &context
skyboxFileExtension = elemSkybox.attribute( "file-ext" );

QDomElement elemDebug = elem.firstChildElement( "debug" );
showBoundingBoxes = elemDebug.attribute( "bounding-boxes", "0" ).toInt();
drawTerrainTileInfo = elemDebug.attribute( "terrain-tile-info", "0" ).toInt();
mShowTerrainBoundingBoxes = elemDebug.attribute( "bounding-boxes", "0" ).toInt();
mShowTerrainTileInfo = elemDebug.attribute( "terrain-tile-info", "0" ).toInt();
}

QDomElement Map3D::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
@@ -225,8 +226,8 @@ QDomElement Map3D::writeXml( QDomDocument &doc, const QgsReadWriteContext &conte
}
elemTerrain.appendChild( elemMapLayers );
QDomElement elemTerrainGenerator = doc.createElement( "generator" );
elemTerrainGenerator.setAttribute( "type", TerrainGenerator::typeToString( terrainGenerator->type() ) );
terrainGenerator->writeXml( elemTerrainGenerator );
elemTerrainGenerator.setAttribute( "type", TerrainGenerator::typeToString( mTerrainGenerator->type() ) );
mTerrainGenerator->writeXml( elemTerrainGenerator );
elemTerrain.appendChild( elemTerrainGenerator );
elem.appendChild( elemTerrain );

@@ -262,8 +263,8 @@ QDomElement Map3D::writeXml( QDomDocument &doc, const QgsReadWriteContext &conte
elem.appendChild( elemSkybox );

QDomElement elemDebug = doc.createElement( "debug" );
elemDebug.setAttribute( "bounding-boxes", showBoundingBoxes ? 1 : 0 );
elemDebug.setAttribute( "terrain-tile-info", drawTerrainTileInfo ? 1 : 0 );
elemDebug.setAttribute( "bounding-boxes", mShowTerrainBoundingBoxes ? 1 : 0 );
elemDebug.setAttribute( "terrain-tile-info", mShowTerrainTileInfo ? 1 : 0 );
elem.appendChild( elemDebug );

return elem;
@@ -277,7 +278,7 @@ void Map3D::resolveReferences( const QgsProject &project )
layerRef.setLayer( project.mapLayer( layerRef.layerId ) );
}

terrainGenerator->resolveReferences( project );
mTerrainGenerator->resolveReferences( project );

for ( int i = 0; i < polygonRenderers.count(); ++i )
{
@@ -306,7 +307,12 @@ void Map3D::setLayers( const QList<QgsMapLayer *> &layers )
{
lst.append( layer );
}

if ( mLayers == lst )
return;

mLayers = lst;
emit layersChanged();
}

QList<QgsMapLayer *> Map3D::layers() const
@@ -321,6 +327,30 @@ QList<QgsMapLayer *> Map3D::layers() const
return lst;
}

void Map3D::setTerrainGenerator( TerrainGenerator *gen )
{
mTerrainGenerator.reset( gen );
emit terrainGeneratorChanged();
}

void Map3D::setShowTerrainBoundingBoxes( bool enabled )
{
if ( mShowTerrainBoundingBoxes == enabled )
return;

mShowTerrainBoundingBoxes = enabled;
emit showTerrainBoundingBoxesChanged();
}

void Map3D::setShowTerrainTilesInfo( bool enabled )
{
if ( mShowTerrainTileInfo == enabled )
return;

mShowTerrainTileInfo = enabled;
emit showTerrainTilesInfoChanged();
}

// ---------------

PolygonRenderer::PolygonRenderer()
@@ -147,8 +147,9 @@ class QgsProject;
class QDomElement;

//! Definition of the world
class _3D_EXPORT Map3D
class _3D_EXPORT Map3D : public QObject
{
Q_OBJECT
public:
Map3D();
Map3D( const Map3D &other );
@@ -175,7 +176,10 @@ class _3D_EXPORT Map3D

int tileTextureSize; //!< Size of map textures of tiles in pixels (width/height)
int maxTerrainError; //!< Maximum allowed terrain error in pixels
std::unique_ptr<TerrainGenerator> terrainGenerator; //!< Implementation of the terrain generation

//! Takes ownership of the generator
void setTerrainGenerator( TerrainGenerator *gen );
TerrainGenerator *terrainGenerator() const { return mTerrainGenerator.get(); }

//
// 3D renderers
@@ -189,10 +193,21 @@ class _3D_EXPORT Map3D
QString skyboxFileBase;
QString skyboxFileExtension;

bool showBoundingBoxes; //!< Whether to show bounding boxes of entities - useful for debugging
bool drawTerrainTileInfo; //!< Whether to draw extra information about terrain tiles to the textures - useful for debugging
void setShowTerrainBoundingBoxes( bool enabled );
bool showTerrainBoundingBoxes() const { return mShowTerrainBoundingBoxes; }
void setShowTerrainTilesInfo( bool enabled );
bool showTerrainTilesInfo() const { return mShowTerrainTileInfo; }

signals:
void layersChanged();
void terrainGeneratorChanged();
void showTerrainBoundingBoxesChanged();
void showTerrainTilesInfoChanged();

private:
std::unique_ptr<TerrainGenerator> mTerrainGenerator; //!< Implementation of the terrain generation
bool mShowTerrainBoundingBoxes; //!< Whether to show bounding boxes of entities - useful for debugging
bool mShowTerrainTileInfo; //!< Whether to draw extra information about terrain tiles to the textures - useful for debugging
QList<QgsMapLayerRef> mLayers; //!< Layers to be rendered
};

@@ -52,7 +52,7 @@ PointEntity::PointEntity( const Map3D &map, const PointRenderer &settings, Qt3DC
{
QgsPoint *pt = static_cast<QgsPoint *>( g );
// TODO: use Z coordinates if the point is 3D
float h = map.terrainGenerator->heightAt( pt->x(), pt->y(), map ) * map.zExaggeration;
float h = map.terrainGenerator()->heightAt( pt->x(), pt->y(), map ) * map.zExaggeration;
positions.append( QVector3D( pt->x() - map.originX, h + settings.height, -( pt->y() - map.originY ) ) );
//qDebug() << positions.last();
}
@@ -25,6 +25,8 @@

Scene::Scene( const Map3D &map, Qt3DExtras::QForwardRenderer *defaultFrameGraph, Qt3DRender::QRenderSettings *renderSettings, Qt3DRender::QCamera *camera, const QRect &viewportRect, Qt3DCore::QNode *parent )
: Qt3DCore::QEntity( parent )
, mMap( map )
, mTerrain( nullptr )
{
defaultFrameGraph->setClearColor( map.backgroundColor );

@@ -53,14 +55,9 @@ Scene::Scene( const Map3D &map, Qt3DExtras::QForwardRenderer *defaultFrameGraph,
mCameraController->resetView();

// create terrain entity
mTerrain = new Terrain( 3, map );
//mTerrain->setEnabled(false);
mTerrain->setParent( this );
// add camera control's terrain picker as a component to be able to capture height where mouse was
// pressed in order to correcly pan camera when draggin mouse
mTerrain->addComponent( mCameraController->terrainPicker() );
if ( map.showBoundingBoxes )
mTerrain->setShowBoundingBoxes( true );

createTerrain();
connect( &map, &Map3D::terrainGeneratorChanged, this, &Scene::createTerrain );

Q_FOREACH ( const PolygonRenderer &pr, map.polygonRenderers )
{
@@ -103,8 +100,6 @@ Scene::Scene( const Map3D &map, Qt3DExtras::QForwardRenderer *defaultFrameGraph,
connect( mCameraController, &CameraController::cameraChanged, this, &Scene::onCameraChanged );
connect( mCameraController, &CameraController::viewportChanged, this, &Scene::onCameraChanged );

chunkEntities << mTerrain;

#if 0
// experiments with loading of existing 3D models.

@@ -182,3 +177,27 @@ void Scene::onFrameTriggered( float dt )
}
}
}

void Scene::createTerrain()
{
if ( mTerrain )
{
chunkEntities.removeOne( mTerrain );

mTerrain->deleteLater();
mTerrain = nullptr;
}

mTerrain = new Terrain( 3, mMap );
//mTerrain->setEnabled(false);
mTerrain->setParent( this );

if ( mMap.showTerrainBoundingBoxes() )
mTerrain->setShowBoundingBoxes( true );

mCameraController->addTerrainPicker( mTerrain->terrainPicker() );

chunkEntities << mTerrain;

onCameraChanged(); // force update of the new terrain
}
@@ -41,8 +41,10 @@ class _3D_EXPORT Scene : public Qt3DCore::QEntity
private slots:
void onCameraChanged();
void onFrameTriggered( float dt );
void createTerrain();

private:
const Map3D &mMap;
//! Provides a way to have a synchronous function executed each frame
Qt3DLogic::QFrameAction *mFrameAction;
CameraController *mCameraController;
@@ -55,7 +55,7 @@ class DemTerrainChunkLoader : public TerrainChunkLoader
virtual void load() override
{
const Map3D &map = mTerrain->map3D();
DemTerrainGenerator *generator = static_cast<DemTerrainGenerator *>( map.terrainGenerator.get() );
DemTerrainGenerator *generator = static_cast<DemTerrainGenerator *>( map.terrainGenerator() );

heightMap = generator->heightMapGenerator()->renderSynchronously( node->x, node->y, node->z );
resolution = generator->heightMapGenerator()->resolution();
@@ -65,7 +65,7 @@ class DemTerrainChunkLoader : public TerrainChunkLoader

virtual Qt3DCore::QEntity *createEntity( Qt3DCore::QEntity *parent )
{
Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
TerrainChunkEntity *entity = new TerrainChunkEntity;

// create geometry renderer

@@ -87,7 +87,7 @@ class DemTerrainChunkLoader : public TerrainChunkLoader
_heightMapMinMax( heightMap, zMin, zMax );

const Map3D &map = mTerrain->map3D();
QgsRectangle extent = map.terrainGenerator->terrainTilingScheme.tileToExtent( node->x, node->y, node->z ); //node->extent;
QgsRectangle extent = map.terrainGenerator()->terrainTilingScheme.tileToExtent( node->x, node->y, node->z ); //node->extent;
double x0 = extent.xMinimum() - map.originX;
double y0 = extent.yMinimum() - map.originY;
double side = extent.width();
@@ -39,7 +39,7 @@ void FlatTerrainChunkLoader::load()

Qt3DCore::QEntity *FlatTerrainChunkLoader::createEntity( Qt3DCore::QEntity *parent )
{
Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
TerrainChunkEntity *entity = new TerrainChunkEntity;

// make geometry renderer

@@ -65,7 +65,7 @@ QImage MapTextureGenerator::renderSynchronously( const QgsRectangle &extent, con
QgsMapRendererCustomPainterJob job( mapSettings, &p );
job.renderSynchronously();

if ( !debugText.isEmpty() )
if ( map.showTerrainTilesInfo() )
{
// extra tile information for debugging
p.setPen( Qt::white );

0 comments on commit 3d9d455

Please sign in to comment.
You can’t perform that action at this time.