Skip to content

Commit

Permalink
Introduced Shape enum for 3D point symbols (from Nyall's review)
Browse files Browse the repository at this point in the history
  • Loading branch information
wonder-sk committed Sep 30, 2017
1 parent 982cfef commit ae3b3ec
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 84 deletions.
40 changes: 40 additions & 0 deletions src/3d/symbols/qgspoint3dsymbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ void QgsPoint3DSymbol::writeXml( QDomElement &elem, const QgsReadWriteContext &c
mMaterial.writeXml( elemMaterial );
elem.appendChild( elemMaterial );

elem.setAttribute( QStringLiteral( "shape" ), shapeToString( mShape ) );

QVariantMap shapePropertiesCopy( mShapeProperties );
shapePropertiesCopy["model"] = QVariant( context.pathResolver().writePath( shapePropertiesCopy["model"].toString() ) );

Expand All @@ -38,10 +40,48 @@ void QgsPoint3DSymbol::readXml( const QDomElement &elem, const QgsReadWriteConte
QDomElement elemMaterial = elem.firstChildElement( QStringLiteral( "material" ) );
mMaterial.readXml( elemMaterial );

mShape = shapeFromString( elem.attribute( QStringLiteral( "shape" ) ) );

QDomElement elemShapeProperties = elem.firstChildElement( QStringLiteral( "shape-properties" ) );
mShapeProperties = QgsXmlUtils::readVariant( elemShapeProperties.firstChildElement() ).toMap();
mShapeProperties["model"] = QVariant( context.pathResolver().readPath( mShapeProperties["model"].toString() ) );

QDomElement elemTransform = elem.firstChildElement( QStringLiteral( "transform" ) );
mTransform = Qgs3DUtils::stringToMatrix4x4( elemTransform.attribute( QStringLiteral( "matrix" ) ) );
}

QgsPoint3DSymbol::Shape QgsPoint3DSymbol::shapeFromString( const QString &shape )
{
if ( shape == QStringLiteral( "sphere" ) )
return Sphere;
else if ( shape == QStringLiteral( "cone" ) )
return Cone;
else if ( shape == QStringLiteral( "cube" ) )
return Cube;
else if ( shape == QStringLiteral( "torus" ) )
return Torus;
else if ( shape == QStringLiteral( "plane" ) )
return Plane;
else if ( shape == QStringLiteral( "extruded-text" ) )
return ExtrudedText;
else if ( shape == QStringLiteral( "model" ) )
return Model;
else // "cylinder" (default)
return Cylinder;
}

QString QgsPoint3DSymbol::shapeToString( QgsPoint3DSymbol::Shape shape )
{
switch ( shape )
{
case Cylinder: return QStringLiteral( "cylinder" );
case Sphere: return QStringLiteral( "sphere" );
case Cone: return QStringLiteral( "cone" );
case Cube: return QStringLiteral( "cube" );
case Torus: return QStringLiteral( "torus" );
case Plane: return QStringLiteral( "plane" );
case ExtrudedText: return QStringLiteral( "extruded-text" );
case Model: return QStringLiteral( "model" );
default: Q_ASSERT( false ); return QString();
}
}
26 changes: 25 additions & 1 deletion src/3d/symbols/qgspoint3dsymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,29 @@ class _3D_EXPORT QgsPoint3DSymbol : public QgsAbstract3DSymbol
//! Sets material used for shading of the symbol
void setMaterial( const QgsPhongMaterialSettings &material ) { mMaterial = material; }

//! 3D shape types supported by the symbol
enum Shape
{
Cylinder,
Sphere,
Cone,
Cube,
Torus,
Plane,
ExtrudedText, //!< Supported in Qt 5.9+
Model,
};

//! Returns shape enum value from a string
static Shape shapeFromString( const QString &shape );
//! Returns string from a shape enum value
static QString shapeToString( Shape shape );

//! Returns 3D shape for points
Shape shape() const { return mShape; }
//! Sets 3D shape for points
void setShape( Shape shape ) { mShape = shape; }

//! Returns a key-value dictionary of point shape properties
QVariantMap shapeProperties() const { return mShapeProperties; }
//! Sets a key-value dictionary of point shape properties
Expand All @@ -41,7 +64,8 @@ class _3D_EXPORT QgsPoint3DSymbol : public QgsAbstract3DSymbol

private:
QgsPhongMaterialSettings mMaterial; //!< Defines appearance of objects
QVariantMap mShapeProperties; //!< What kind of shape to use and what
Shape mShape = Cylinder; //!< What kind of shape to use
QVariantMap mShapeProperties; //!< Key-value dictionary of shape's properties (different keys for each shape)
QMatrix4x4 mTransform; //!< Transform of individual instanced models
};

Expand Down
160 changes: 87 additions & 73 deletions src/3d/symbols/qgspoint3dsymbol_p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
QgsPoint3DSymbolEntity::QgsPoint3DSymbolEntity( const Qgs3DMapSettings &map, QgsVectorLayer *layer, const QgsPoint3DSymbol &symbol, Qt3DCore::QNode *parent )
: Qt3DCore::QEntity( parent )
{
if ( symbol.shapeProperties()["shape"].toString() == "model" )
if ( symbol.shape() == QgsPoint3DSymbol::Model )
{
QgsPoint3DSymbolModelEntityFactory::addEntitiesForSelectedPoints( map, layer, symbol, this );
QgsPoint3DSymbolModelEntityFactory::addEntitiesForNotSelectedPoints( map, layer, symbol, this );
Expand Down Expand Up @@ -199,78 +199,7 @@ Qt3DRender::QGeometryRenderer *QgsPoint3DSymbolInstancedEntityNode::renderer( co
instanceDataAttribute->setCount( count );
instanceDataAttribute->setByteStride( 3 * sizeof( float ) );

Qt3DRender::QGeometry *geometry = nullptr;
QVariantMap shapeProperties = symbol.shapeProperties();
QString shape = shapeProperties["shape"].toString();
if ( shape == "sphere" )
{
float radius = shapeProperties["radius"].toFloat();
Qt3DExtras::QSphereGeometry *g = new Qt3DExtras::QSphereGeometry;
g->setRadius( radius ? radius : 10 );
geometry = g;
}
else if ( shape == "cone" )
{
float length = shapeProperties["length"].toFloat();
float bottomRadius = shapeProperties["bottomRadius"].toFloat();
float topRadius = shapeProperties["topRadius"].toFloat();
Qt3DExtras::QConeGeometry *g = new Qt3DExtras::QConeGeometry;
g->setLength( length ? length : 10 );
g->setBottomRadius( bottomRadius );
g->setTopRadius( topRadius );
//g->setHasBottomEndcap(hasBottomEndcap);
//g->setHasTopEndcap(hasTopEndcap);
geometry = g;
}
else if ( shape == "cube" )
{
float size = shapeProperties["size"].toFloat();
Qt3DExtras::QCuboidGeometry *g = new Qt3DExtras::QCuboidGeometry;
g->setXExtent( size ? size : 10 );
g->setYExtent( size ? size : 10 );
g->setZExtent( size ? size : 10 );
geometry = g;
}
else if ( shape == "torus" )
{
float radius = shapeProperties["radius"].toFloat();
float minorRadius = shapeProperties["minorRadius"].toFloat();
Qt3DExtras::QTorusGeometry *g = new Qt3DExtras::QTorusGeometry;
g->setRadius( radius ? radius : 10 );
g->setMinorRadius( minorRadius ? minorRadius : 5 );
geometry = g;
}
else if ( shape == "plane" )
{
float size = shapeProperties["size"].toFloat();
Qt3DExtras::QPlaneGeometry *g = new Qt3DExtras::QPlaneGeometry;
g->setWidth( size ? size : 10 );
g->setHeight( size ? size : 10 );
geometry = g;
}
#if QT_VERSION >= 0x050900
else if ( shape == "extrudedText" )
{
float depth = shapeProperties["depth"].toFloat();
QString text = shapeProperties["text"].toString();
Qt3DExtras::QExtrudedTextGeometry *g = new Qt3DExtras::QExtrudedTextGeometry;
g->setDepth( depth ? depth : 1 );
g->setText( text );
geometry = g;
}
#endif
else // shape == "cylinder" or anything else
{
float radius = shapeProperties["radius"].toFloat();
float length = shapeProperties["length"].toFloat();
Qt3DExtras::QCylinderGeometry *g = new Qt3DExtras::QCylinderGeometry;
//g->setRings(2); // how many vertices vertically
//g->setSlices(8); // how many vertices on circumference
g->setRadius( radius ? radius : 10 );
g->setLength( length ? length : 10 );
geometry = g;
}

Qt3DRender::QGeometry *geometry = symbolGeometry( symbol.shape(), symbol.shapeProperties() );
geometry->addAttribute( instanceDataAttribute );
geometry->setBoundingVolumePositionAttribute( instanceDataAttribute );

Expand All @@ -281,6 +210,91 @@ Qt3DRender::QGeometryRenderer *QgsPoint3DSymbolInstancedEntityNode::renderer( co
return renderer;
}

Qt3DRender::QGeometry *QgsPoint3DSymbolInstancedEntityNode::symbolGeometry( QgsPoint3DSymbol::Shape shape, const QVariantMap &shapeProperties ) const
{
switch ( shape )
{
case QgsPoint3DSymbol::Cylinder:
{
float radius = shapeProperties["radius"].toFloat();
float length = shapeProperties["length"].toFloat();
Qt3DExtras::QCylinderGeometry *g = new Qt3DExtras::QCylinderGeometry;
//g->setRings(2); // how many vertices vertically
//g->setSlices(8); // how many vertices on circumference
g->setRadius( radius ? radius : 10 );
g->setLength( length ? length : 10 );
return g;
}

case QgsPoint3DSymbol::Sphere:
{
float radius = shapeProperties["radius"].toFloat();
Qt3DExtras::QSphereGeometry *g = new Qt3DExtras::QSphereGeometry;
g->setRadius( radius ? radius : 10 );
return g;
}

case QgsPoint3DSymbol::Cone:
{
float length = shapeProperties["length"].toFloat();
float bottomRadius = shapeProperties["bottomRadius"].toFloat();
float topRadius = shapeProperties["topRadius"].toFloat();
Qt3DExtras::QConeGeometry *g = new Qt3DExtras::QConeGeometry;
g->setLength( length ? length : 10 );
g->setBottomRadius( bottomRadius );
g->setTopRadius( topRadius );
//g->setHasBottomEndcap(hasBottomEndcap);
//g->setHasTopEndcap(hasTopEndcap);
return g;
}

case QgsPoint3DSymbol::Cube:
{
float size = shapeProperties["size"].toFloat();
Qt3DExtras::QCuboidGeometry *g = new Qt3DExtras::QCuboidGeometry;
g->setXExtent( size ? size : 10 );
g->setYExtent( size ? size : 10 );
g->setZExtent( size ? size : 10 );
return g;
}

case QgsPoint3DSymbol::Torus:
{
float radius = shapeProperties["radius"].toFloat();
float minorRadius = shapeProperties["minorRadius"].toFloat();
Qt3DExtras::QTorusGeometry *g = new Qt3DExtras::QTorusGeometry;
g->setRadius( radius ? radius : 10 );
g->setMinorRadius( minorRadius ? minorRadius : 5 );
return g;
}

case QgsPoint3DSymbol::Plane:
{
float size = shapeProperties["size"].toFloat();
Qt3DExtras::QPlaneGeometry *g = new Qt3DExtras::QPlaneGeometry;
g->setWidth( size ? size : 10 );
g->setHeight( size ? size : 10 );
return g;
}

#if QT_VERSION >= 0x050900
case QgsPoint3DSymbol::ExtrudedText:
{
float depth = shapeProperties["depth"].toFloat();
QString text = shapeProperties["text"].toString();
Qt3DExtras::QExtrudedTextGeometry *g = new Qt3DExtras::QExtrudedTextGeometry;
g->setDepth( depth ? depth : 1 );
g->setText( text );
return g;
}
#endif

default:
Q_ASSERT( false );
return nullptr;
}
}

//* 3D MODEL RENDERING *//

static Qt3DExtras::QPhongMaterial *phongMaterial( const QgsPoint3DSymbol &symbol )
Expand Down
3 changes: 3 additions & 0 deletions src/3d/symbols/qgspoint3dsymbol_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include <Qt3DRender/QGeometryRenderer>
#include <Qt3DCore/QTransform>

#include "qgspoint3dsymbol.h"

class Qgs3DMapSettings;
class QgsPoint3DSymbol;

Expand Down Expand Up @@ -48,6 +50,7 @@ class QgsPoint3DSymbolInstancedEntityNode : public Qt3DCore::QEntity

private:
Qt3DRender::QGeometryRenderer *renderer( const QgsPoint3DSymbol &symbol, const QList<QVector3D> &positions ) const;
Qt3DRender::QGeometry *symbolGeometry( QgsPoint3DSymbol::Shape shape, const QVariantMap &shapeProperties ) const;
};

class QgsPoint3DSymbolModelEntityFactory
Expand Down
19 changes: 9 additions & 10 deletions src/app/3d/qgspoint3dsymbolwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ QgsPoint3DSymbolWidget::QgsPoint3DSymbolWidget( QWidget *parent )
{
setupUi( this );

cboShape->addItem( tr( "Sphere" ), "sphere" );
cboShape->addItem( tr( "Cylinder" ), "cylinder" );
cboShape->addItem( tr( "Cube" ), "cube" );
cboShape->addItem( tr( "Cone" ), "cone" );
cboShape->addItem( tr( "Plane" ), "plane" );
cboShape->addItem( tr( "Torus" ), "torus" );
cboShape->addItem( tr( "3D Model" ), "model" );
cboShape->addItem( tr( "Sphere" ), QgsPoint3DSymbol::Sphere );
cboShape->addItem( tr( "Cylinder" ), QgsPoint3DSymbol::Cylinder );
cboShape->addItem( tr( "Cube" ), QgsPoint3DSymbol::Cube );
cboShape->addItem( tr( "Cone" ), QgsPoint3DSymbol::Cone );
cboShape->addItem( tr( "Plane" ), QgsPoint3DSymbol::Plane );
cboShape->addItem( tr( "Torus" ), QgsPoint3DSymbol::Torus );
cboShape->addItem( tr( "3D Model" ), QgsPoint3DSymbol::Model );

setSymbol( QgsPoint3DSymbol() );
onShapeChanged();
Expand Down Expand Up @@ -72,7 +72,7 @@ void QgsPoint3DSymbolWidget::onOverwriteMaterialChecked( int state )
void QgsPoint3DSymbolWidget::setSymbol( const QgsPoint3DSymbol &symbol )
{
QVariantMap vm = symbol.shapeProperties();
int index = cboShape->findData( vm["shape"] );
int index = cboShape->findData( symbol.shape() );
cboShape->setCurrentIndex( index != -1 ? index : 1 ); // use cylinder by default if shape is not set

widgetMaterial->setEnabled( true );
Expand Down Expand Up @@ -141,8 +141,6 @@ void QgsPoint3DSymbolWidget::setSymbol( const QgsPoint3DSymbol &symbol )
QgsPoint3DSymbol QgsPoint3DSymbolWidget::symbol() const
{
QVariantMap vm;
vm["shape"] = cboShape->itemData( cboShape->currentIndex() );

switch ( cboShape->currentIndex() )
{
case 0: // sphere
Expand Down Expand Up @@ -183,6 +181,7 @@ QgsPoint3DSymbol QgsPoint3DSymbolWidget::symbol() const
tr.rotate( rot );

QgsPoint3DSymbol sym;
sym.setShape( ( QgsPoint3DSymbol::Shape ) cboShape->itemData( cboShape->currentIndex() ).toInt() );
sym.setShapeProperties( vm );
sym.setMaterial( widgetMaterial->material() );
sym.setTransform( tr );
Expand Down

0 comments on commit ae3b3ec

Please sign in to comment.