Skip to content

Commit

Permalink
Merge pull request #33480 from wonder-sk/3d-layers-load-in-background
Browse files Browse the repository at this point in the history
[3d] Load 3D vector layer data in background + tiling
  • Loading branch information
wonder-sk committed Jan 16, 2020
2 parents f39d53b + ee92e10 commit a5c9b39
Show file tree
Hide file tree
Showing 45 changed files with 1,648 additions and 236 deletions.
4 changes: 2 additions & 2 deletions external/poly2tri/common/shapes.h
Expand Up @@ -132,11 +132,11 @@ struct Edge {
if (p1.y > p2.y) {
q = &p1;
p = &p2;
} else if (std::abs(p1.y - p2.y) < 1e-10) {
} else if (p1.y == p2.y) {
if (p1.x > p2.x) {
q = &p1;
p = &p2;
} else if (std::abs(p1.x - p2.x) < 1e-10) {
} else if (p1.x == p2.x) {
// Repeat points
throw std::runtime_error("Edge::Edge: p1 == p2");
}
Expand Down
1 change: 1 addition & 0 deletions python/3d/3d_auto.sip
@@ -1,5 +1,6 @@
// Include auto-generated SIP files
%Include auto_generated/qgs3dtypes.sip
%Include auto_generated/qgsabstractvectorlayer3drenderer.sip
%Include auto_generated/qgsphongmaterialsettings.sip
%Include auto_generated/qgsrulebased3drenderer.sip
%Include auto_generated/qgsvectorlayer3drenderer.sip
Expand Down
122 changes: 122 additions & 0 deletions python/3d/auto_generated/qgsabstractvectorlayer3drenderer.sip.in
@@ -0,0 +1,122 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/3d/qgsabstractvectorlayer3drenderer.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/





class QgsVectorLayer3DTilingSettings
{
%Docstring
This class defines configuration of how a vector layer gets tiled for 3D rendering.

Zoom levels count tells how deep will be the quadtree and thus how many tiles will
be generated ( 4 ^ (count-1) ). So for example, for count=1 there will be just
a single tile for the whole layer, for count=3 there will be 16 tiles.

.. versionadded:: 3.12
%End

%TypeHeaderCode
#include "qgsabstractvectorlayer3drenderer.h"
%End
public:

int zoomLevelsCount() const;
%Docstring
Returns number of zoom levels. One zoom level means there will be one tile.
Every extra zoom level multiplies number of tiles by four. For example, three
zoom levels will produce 16 tiles at the highest zoom level. It is therefore
recommended to keep the number of zoom levels low to prevent excessive number
of tiles.
%End

void setZoomLevelsCount( int count );
%Docstring
Sets number of zoom levels. See zoomLevelsCount() documentation for more details.
%End

void setShowBoundingBoxes( bool enabled );
%Docstring
Sets whether to display bounding boxes of entity's tiles (for debugging)
%End
bool showBoundingBoxes() const;
%Docstring
Returns whether to display bounding boxes of entity's tiles (for debugging)
%End

void writeXml( QDomElement &elem ) const;
%Docstring
Writes content of the object to XML
%End
void readXml( const QDomElement &elem );
%Docstring
Reads content of the object from XML
%End

};


class QgsAbstractVectorLayer3DRenderer : QgsAbstract3DRenderer /Abstract/
{
%Docstring
Base class for 3D renderers that are based on vector layers.

.. versionadded:: 3.12
%End

%TypeHeaderCode
#include "qgsabstractvectorlayer3drenderer.h"
%End
public:
QgsAbstractVectorLayer3DRenderer();

void setLayer( QgsVectorLayer *layer );
%Docstring
Sets vector layer associated with the renderer
%End
QgsVectorLayer *layer() const;
%Docstring
Returns vector layer associated with the renderer
%End

void setTilingSettings( const QgsVectorLayer3DTilingSettings &settings );
%Docstring
Sets tiling settings of the renderer
%End
QgsVectorLayer3DTilingSettings tilingSettings() const;
%Docstring
Returns tiling settings of the renderer
%End

virtual void resolveReferences( const QgsProject &project );


protected:
void copyBaseProperties( QgsAbstractVectorLayer3DRenderer *r ) const;
%Docstring
Copies common properties of this object to another object
%End
void writeXmlBaseProperties( QDomElement &elem, const QgsReadWriteContext &context ) const;
%Docstring
Writes common properties of this object to DOM element
%End
void readXmlBaseProperties( const QDomElement &elem, const QgsReadWriteContext &context );
%Docstring
Reads common properties of this object from DOM element
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/3d/qgsabstractvectorlayer3drenderer.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
13 changes: 1 addition & 12 deletions python/3d/auto_generated/qgsrulebased3drenderer.sip.in
Expand Up @@ -39,7 +39,7 @@ Creates an instance of a 3D renderer based on a DOM element with renderer config
};


class QgsRuleBased3DRenderer : QgsAbstract3DRenderer
class QgsRuleBased3DRenderer : QgsAbstractVectorLayer3DRenderer
{
%Docstring
Rule-based 3D renderer.
Expand Down Expand Up @@ -244,15 +244,6 @@ Construct renderer with the given root rule (takes ownership)
%End
~QgsRuleBased3DRenderer();

void setLayer( QgsVectorLayer *layer );
%Docstring
Sets vector layer associated with the renderer
%End
QgsVectorLayer *layer() const;
%Docstring
Returns vector layer associated with the renderer
%End

QgsRuleBased3DRenderer::Rule *rootRule();
%Docstring
Returns pointer to the root rule
Expand All @@ -266,8 +257,6 @@ Returns pointer to the root rule

virtual void readXml( const QDomElement &elem, const QgsReadWriteContext &context );

virtual void resolveReferences( const QgsProject &project );


};

Expand Down
13 changes: 1 addition & 12 deletions python/3d/auto_generated/qgsvectorlayer3drenderer.sip.in
Expand Up @@ -41,7 +41,7 @@ Creates an instance of a 3D renderer based on a DOM element with renderer config
};


class QgsVectorLayer3DRenderer : QgsAbstract3DRenderer
class QgsVectorLayer3DRenderer : QgsAbstractVectorLayer3DRenderer
{
%Docstring
3D renderer that renders all features of a vector layer with the same 3D symbol.
Expand All @@ -57,15 +57,6 @@ The appearance is completely defined by the symbol.
explicit QgsVectorLayer3DRenderer( QgsAbstract3DSymbol *s /Transfer/ = 0 );
%Docstring
Takes ownership of the symbol object
%End

void setLayer( QgsVectorLayer *layer );
%Docstring
Sets vector layer associated with the renderer
%End
QgsVectorLayer *layer() const;
%Docstring
Returns vector layer associated with the renderer
%End

void setSymbol( QgsAbstract3DSymbol *symbol /Transfer/ );
Expand All @@ -85,8 +76,6 @@ Returns 3D symbol associated with the renderer

virtual void readXml( const QDomElement &elem, const QgsReadWriteContext &context );

virtual void resolveReferences( const QgsProject &project );


private:
QgsVectorLayer3DRenderer( const QgsVectorLayer3DRenderer & );
Expand Down
14 changes: 14 additions & 0 deletions python/core/auto_generated/qgstessellator.sip.in
Expand Up @@ -66,6 +66,20 @@ Returns size of one vertex entry in bytes
%End


float zMinimum() const;
%Docstring
Returns minimal Z value of the data (in world coordinates)

.. versionadded:: 3.12
%End

float zMaximum() const;
%Docstring
Returns maximal Z value of the data (in world coordinates)

.. versionadded:: 3.12
%End

};

/************************************************************************
Expand Down
6 changes: 6 additions & 0 deletions src/3d/CMakeLists.txt
Expand Up @@ -4,6 +4,7 @@
SET(QGIS_3D_SRCS
qgsaabb.cpp
qgsabstract3dengine.cpp
qgsabstractvectorlayer3drenderer.cpp
qgs3danimationsettings.cpp
qgs3dmapscene.cpp
qgs3dmapsettings.cpp
Expand All @@ -17,9 +18,11 @@ SET(QGIS_3D_SRCS
qgspointlightsettings.cpp
qgsraycastingutils_p.cpp
qgsrulebased3drenderer.cpp
qgsrulebasedchunkloader_p.cpp
qgstessellatedpolygongeometry.cpp
qgstilingscheme.cpp
qgsvectorlayer3drenderer.cpp
qgsvectorlayerchunkloader_p.cpp
qgsmeshlayer3drenderer.cpp
qgswindow3dengine.cpp

Expand Down Expand Up @@ -70,6 +73,7 @@ SET(QGIS_3D_HDRS
qgs3dutils.h
qgsaabb.h
qgsabstract3dengine.h
qgsabstractvectorlayer3drenderer.h
qgscameracontroller.h
qgscamerapose.h
qgslayoutitem3dmap.h
Expand Down Expand Up @@ -100,6 +104,8 @@ SET(QGIS_3D_HDRS
)

SET(QGIS_3D_PRIVATE_HDRS
qgsrulebasedchunkloader_p.h
qgsvectorlayerchunkloader_p.h
chunks/qgschunkboundsentity_p.h
chunks/qgschunkedentity_p.h
chunks/qgschunklist_p.h
Expand Down
82 changes: 80 additions & 2 deletions src/3d/chunks/qgschunkedentity_p.cpp
Expand Up @@ -17,12 +17,15 @@

#include <QElapsedTimer>
#include <QVector4D>
#include <Qt3DRender/QObjectPicker>
#include <Qt3DRender/QPickTriangleEvent>

#include "qgs3dutils.h"
#include "qgschunkboundsentity_p.h"
#include "qgschunklist_p.h"
#include "qgschunkloader_p.h"
#include "qgschunknode_p.h"
#include "qgstessellatedpolygongeometry.h"

#include "qgseventtracing.h"

Expand Down Expand Up @@ -244,9 +247,9 @@ void QgsChunkedEntity::update( QgsChunkNode *node, const SceneState &state )
return;
}

//qDebug() << node->x << "|" << node->y << "|" << node->z << " " << tau << " " << screenSpaceError(node, state);
//qDebug() << node->tileX() << "|" << node->tileY() << "|" << node->tileZ() << " " << mTau << " " << screenSpaceError(node, state);

if ( screenSpaceError( node, state ) <= mTau )
if ( mTau > 0 && screenSpaceError( node, state ) <= mTau )
{
// acceptable error for the current chunk - let's render it

Expand Down Expand Up @@ -343,6 +346,15 @@ void QgsChunkedEntity::onActiveJobFinished()
node->setLoaded( entity );

mReplacementQueue->insertFirst( node->replacementQueueEntry() );

if ( mPickingEnabled )
{
Qt3DRender::QObjectPicker *picker = new Qt3DRender::QObjectPicker( node->entity() );
node->entity()->addComponent( picker );
connect( picker, &Qt3DRender::QObjectPicker::clicked, this, &QgsChunkedEntity::onPickEvent );
}

emit newEntityCreated( entity );
}
else
{
Expand Down Expand Up @@ -450,4 +462,70 @@ void QgsChunkedEntity::cancelActiveJobs()
}
}


void QgsChunkedEntity::setPickingEnabled( bool enabled )
{
if ( mPickingEnabled == enabled )
return;

mPickingEnabled = enabled;

if ( enabled )
{
QgsChunkListEntry *entry = mReplacementQueue->first();
while ( entry )
{
QgsChunkNode *node = entry->chunk;
Qt3DRender::QObjectPicker *picker = new Qt3DRender::QObjectPicker( node->entity() );
node->entity()->addComponent( picker );
connect( picker, &Qt3DRender::QObjectPicker::clicked, this, &QgsChunkedEntity::onPickEvent );

entry = entry->next;
}
}
else
{
for ( Qt3DRender::QObjectPicker *picker : findChildren<Qt3DRender::QObjectPicker *>() )
picker->deleteLater();
}
}

void QgsChunkedEntity::onPickEvent( Qt3DRender::QPickEvent *event )
{
Qt3DRender::QPickTriangleEvent *triangleEvent = qobject_cast<Qt3DRender::QPickTriangleEvent *>( event );
if ( !triangleEvent )
return;

Qt3DRender::QObjectPicker *picker = qobject_cast<Qt3DRender::QObjectPicker *>( sender() );
if ( !picker )
return;

Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>( picker->parent() );
if ( !entity )
return;

// go figure out feature ID from the triangle index
QgsFeatureId fid = FID_NULL;
for ( Qt3DRender::QGeometryRenderer *geomRenderer : entity->findChildren<Qt3DRender::QGeometryRenderer *>() )
{
// unfortunately we can't access which sub-entity triggered the pick event
// so as a temporary workaround let's just ignore the entity with selection
// and hope the event was the main entity (QTBUG-58206)
if ( geomRenderer->objectName() != QLatin1String( "main" ) )
continue;

if ( QgsTessellatedPolygonGeometry *g = qobject_cast<QgsTessellatedPolygonGeometry *>( geomRenderer->geometry() ) )
{
fid = g->triangleIndexToFeatureId( triangleEvent->triangleIndex() );
if ( !FID_IS_NULL( fid ) )
break;
}
}

if ( !FID_IS_NULL( fid ) )
{
emit pickedObject( event, fid );
}
}

/// @endcond

0 comments on commit a5c9b39

Please sign in to comment.