[Feature] directional lights support for QGIS 3D

This commit is contained in:
nedjima 2020-06-07 00:24:46 +01:00 committed by Nyall Dawson
parent 672d6ec5b2
commit 9556bd2147
13 changed files with 734 additions and 183 deletions

View File

@ -7,6 +7,7 @@
%Include auto_generated/qgslayoutitem3dmap.sip %Include auto_generated/qgslayoutitem3dmap.sip
%Include auto_generated/qgsphongmaterialsettings.sip %Include auto_generated/qgsphongmaterialsettings.sip
%Include auto_generated/qgspointlightsettings.sip %Include auto_generated/qgspointlightsettings.sip
%Include auto_generated/qgsdirectionallightsettings.sip
%Include auto_generated/qgsrulebased3drenderer.sip %Include auto_generated/qgsrulebased3drenderer.sip
%Include auto_generated/qgsvectorlayer3drenderer.sip %Include auto_generated/qgsvectorlayer3drenderer.sip
%Include auto_generated/symbols/qgsabstract3dsymbol.sip %Include auto_generated/symbols/qgsabstract3dsymbol.sip

View File

@ -366,6 +366,13 @@ Returns whether to display labels on terrain tiles
Returns list of point lights defined in the scene Returns list of point lights defined in the scene
.. versionadded:: 3.6 .. versionadded:: 3.6
%End
QList<QgsDirectionalLightSettings> directionalLights() const;
%Docstring
Returns list of directional lights defined in the scene
.. versionadded:: 3.16
%End %End
void setPointLights( const QList<QgsPointLightSettings> &pointLights ); void setPointLights( const QList<QgsPointLightSettings> &pointLights );
@ -373,6 +380,13 @@ Returns list of point lights defined in the scene
Sets list of point lights defined in the scene Sets list of point lights defined in the scene
.. versionadded:: 3.6 .. versionadded:: 3.6
%End
void setDirectionalLights( const QList<QgsDirectionalLightSettings> &pointLights );
%Docstring
Sets list of directional lights defined in the scene
.. versionadded:: 3.16
%End %End
float fieldOfView() const; float fieldOfView() const;
@ -487,6 +501,13 @@ Emitted when the flag whether labels are displayed on terrain tiles has changed
Emitted when the list of point lights changes Emitted when the list of point lights changes
.. versionadded:: 3.6 .. versionadded:: 3.6
%End
void directionalLightsChanged();
%Docstring
Emitted when the list of directional lights changes
.. versionadded:: 3.16
%End %End
void fieldOfViewChanged(); void fieldOfViewChanged();

View File

@ -0,0 +1,75 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/3d/qgsdirectionallightsettings.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsDirectionalLightSettings
{
%Docstring
Definition of a directional light in a 3D map scene
.. versionadded:: 3.16
%End
%TypeHeaderCode
#include "qgsdirectionallightsettings.h"
%End
public:
QgsDirectionalLightSettings();
%Docstring
Construct a directional light with default values
%End
QgsVector3D direction() const;
%Docstring
Returns the direction of the light in degrees
%End
void setDirection( const QgsVector3D &direction );
%Docstring
Sets the direction of the light in degrees
%End
QColor color() const;
%Docstring
Returns color of the light
%End
void setColor( const QColor &color );
%Docstring
Sets color of the light
%End
float intensity() const;
%Docstring
Returns intensity of the light
%End
void setIntensity( float intensity );
%Docstring
Sets intensity of the light
%End
QDomElement writeXml( QDomDocument &doc ) const;
%Docstring
Writes configuration to a new DOM element and returns it
%End
void readXml( const QDomElement &elem );
%Docstring
Reads configuration from a DOM element previously written using writeXml()
%End
bool operator==( const QgsDirectionalLightSettings &other );
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/3d/qgsdirectionallightsettings.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -16,6 +16,7 @@ SET(QGIS_3D_SRCS
qgsoffscreen3dengine.cpp qgsoffscreen3dengine.cpp
qgsphongmaterialsettings.cpp qgsphongmaterialsettings.cpp
qgspointlightsettings.cpp qgspointlightsettings.cpp
qgsdirectionallightsettings.cpp
qgsraycastingutils_p.cpp qgsraycastingutils_p.cpp
qgsrulebased3drenderer.cpp qgsrulebased3drenderer.cpp
qgsrulebasedchunkloader_p.cpp qgsrulebasedchunkloader_p.cpp
@ -87,6 +88,7 @@ SET(QGIS_3D_HDRS
qgsoffscreen3dengine.h qgsoffscreen3dengine.h
qgsphongmaterialsettings.h qgsphongmaterialsettings.h
qgspointlightsettings.h qgspointlightsettings.h
qgsdirectionallightsettings.h
qgsrulebased3drenderer.h qgsrulebased3drenderer.h
qgstessellatedpolygongeometry.h qgstessellatedpolygongeometry.h
qgstilingscheme.h qgstilingscheme.h

View File

@ -22,6 +22,7 @@
#include <Qt3DRender/QPickingSettings> #include <Qt3DRender/QPickingSettings>
#include <Qt3DRender/QPickTriangleEvent> #include <Qt3DRender/QPickTriangleEvent>
#include <Qt3DRender/QPointLight> #include <Qt3DRender/QPointLight>
#include <Qt3DRender/QDirectionalLight>
#include <Qt3DRender/QRenderSettings> #include <Qt3DRender/QRenderSettings>
#include <Qt3DRender/QSceneLoader> #include <Qt3DRender/QSceneLoader>
#include <Qt3DExtras/QForwardRenderer> #include <Qt3DExtras/QForwardRenderer>
@ -103,6 +104,7 @@ Qgs3DMapScene::Qgs3DMapScene( const Qgs3DMapSettings &map, QgsAbstract3DEngine *
connect( &map, &Qgs3DMapSettings::maxTerrainGroundErrorChanged, this, &Qgs3DMapScene::createTerrain ); connect( &map, &Qgs3DMapSettings::maxTerrainGroundErrorChanged, this, &Qgs3DMapScene::createTerrain );
connect( &map, &Qgs3DMapSettings::terrainShadingChanged, this, &Qgs3DMapScene::createTerrain ); connect( &map, &Qgs3DMapSettings::terrainShadingChanged, this, &Qgs3DMapScene::createTerrain );
connect( &map, &Qgs3DMapSettings::pointLightsChanged, this, &Qgs3DMapScene::updateLights ); connect( &map, &Qgs3DMapSettings::pointLightsChanged, this, &Qgs3DMapScene::updateLights );
connect( &map, &Qgs3DMapSettings::directionalLightsChanged, this, &Qgs3DMapScene::updateLights );
connect( &map, &Qgs3DMapSettings::fieldOfViewChanged, this, &Qgs3DMapScene::updateCameraLens ); connect( &map, &Qgs3DMapSettings::fieldOfViewChanged, this, &Qgs3DMapScene::updateCameraLens );
connect( &map, &Qgs3DMapSettings::renderersChanged, this, &Qgs3DMapScene::onRenderersChanged ); connect( &map, &Qgs3DMapSettings::renderersChanged, this, &Qgs3DMapScene::onRenderersChanged );
@ -474,6 +476,24 @@ void Qgs3DMapScene::updateLights()
lightEntity->setParent( this ); lightEntity->setParent( this );
mLightEntities << lightEntity; mLightEntities << lightEntity;
} }
const auto newDirectionalLights = mMap.directionalLights();
for ( const QgsDirectionalLightSettings &pointLightSettings : newDirectionalLights )
{
Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity;
Qt3DCore::QTransform *lightTransform = new Qt3DCore::QTransform;
Qt3DRender::QDirectionalLight *light = new Qt3DRender::QDirectionalLight;
light->setColor( pointLightSettings.color() );
light->setIntensity( pointLightSettings.intensity() );
QgsVector3D direction = pointLightSettings.direction();
light->setWorldDirection( QVector3D( direction.x(), direction.y(), direction.z() ) );
lightEntity->addComponent( light );
lightEntity->addComponent( lightTransform );
lightEntity->setParent( this );
mLightEntities << lightEntity;
}
} }
void Qgs3DMapScene::updateCameraLens() void Qgs3DMapScene::updateCameraLens()

View File

@ -49,6 +49,7 @@ Qgs3DMapSettings::Qgs3DMapSettings( const Qgs3DMapSettings &other )
, mShowCameraViewCenter( other.mShowCameraViewCenter ) , mShowCameraViewCenter( other.mShowCameraViewCenter )
, mShowLabels( other.mShowLabels ) , mShowLabels( other.mShowLabels )
, mPointLights( other.mPointLights ) , mPointLights( other.mPointLights )
, mDirectionalLights( other.mDirectionalLights )
, mFieldOfView( other.mFieldOfView ) , mFieldOfView( other.mFieldOfView )
, mLayers( other.mLayers ) , mLayers( other.mLayers )
, mRenderers() // initialized in body , mRenderers() // initialized in body
@ -127,6 +128,20 @@ void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteConte
mPointLights << defaultLight; mPointLights << defaultLight;
} }
mDirectionalLights.clear();
QDomElement elemDirectionalLights = elem.firstChildElement( QStringLiteral( "directional-lights" ) );
if ( !elemDirectionalLights.isNull() )
{
QDomElement elemDirectionalLight = elemDirectionalLights.firstChildElement( QStringLiteral( "directional-light" ) );
while ( !elemDirectionalLight.isNull() )
{
QgsDirectionalLightSettings directionalLight;
directionalLight.readXml( elemDirectionalLight );
mDirectionalLights << directionalLight;
elemDirectionalLight = elemDirectionalLight.nextSiblingElement( QStringLiteral( "directional-light" ) );
}
}
QDomElement elemMapLayers = elemTerrain.firstChildElement( QStringLiteral( "layers" ) ); QDomElement elemMapLayers = elemTerrain.firstChildElement( QStringLiteral( "layers" ) );
QDomElement elemMapLayer = elemMapLayers.firstChildElement( QStringLiteral( "layer" ) ); QDomElement elemMapLayer = elemMapLayers.firstChildElement( QStringLiteral( "layer" ) );
QList<QgsMapLayerRef> mapLayers; QList<QgsMapLayerRef> mapLayers;
@ -250,6 +265,14 @@ QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteCon
} }
elem.appendChild( elemPointLights ); elem.appendChild( elemPointLights );
QDomElement elemDirectionalLights = doc.createElement( QStringLiteral( "directional-lights" ) );
for ( const QgsDirectionalLightSettings &directionalLight : qgis::as_const( mDirectionalLights ) )
{
QDomElement elemDirectionalLight = directionalLight.writeXml( doc );
elemDirectionalLights.appendChild( elemDirectionalLight );
}
elem.appendChild( elemDirectionalLights );
QDomElement elemMapLayers = doc.createElement( QStringLiteral( "layers" ) ); QDomElement elemMapLayers = doc.createElement( QStringLiteral( "layers" ) );
Q_FOREACH ( const QgsMapLayerRef &layerRef, mLayers ) Q_FOREACH ( const QgsMapLayerRef &layerRef, mLayers )
{ {
@ -535,6 +558,15 @@ void Qgs3DMapSettings::setPointLights( const QList<QgsPointLightSettings> &point
emit pointLightsChanged(); emit pointLightsChanged();
} }
void Qgs3DMapSettings::setDirectionalLights( const QList<QgsDirectionalLightSettings> &directionalLights )
{
if ( mDirectionalLights == directionalLights )
return;
mDirectionalLights = directionalLights;
emit directionalLightsChanged();
}
void Qgs3DMapSettings::setFieldOfView( const float fieldOfView ) void Qgs3DMapSettings::setFieldOfView( const float fieldOfView )
{ {
if ( mFieldOfView == fieldOfView ) if ( mFieldOfView == fieldOfView )

View File

@ -27,6 +27,7 @@
#include "qgsmesh3dsymbol.h" #include "qgsmesh3dsymbol.h"
#include "qgsphongmaterialsettings.h" #include "qgsphongmaterialsettings.h"
#include "qgspointlightsettings.h" #include "qgspointlightsettings.h"
#include "qgsdirectionallightsettings.h"
#include "qgsterraingenerator.h" #include "qgsterraingenerator.h"
#include "qgsvector3d.h" #include "qgsvector3d.h"
@ -325,12 +326,24 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
*/ */
QList<QgsPointLightSettings> pointLights() const { return mPointLights; } QList<QgsPointLightSettings> pointLights() const { return mPointLights; }
/**
* Returns list of directional lights defined in the scene
* \since QGIS 3.16
*/
QList<QgsDirectionalLightSettings> directionalLights() const { return mDirectionalLights; }
/** /**
* Sets list of point lights defined in the scene * Sets list of point lights defined in the scene
* \since QGIS 3.6 * \since QGIS 3.6
*/ */
void setPointLights( const QList<QgsPointLightSettings> &pointLights ); void setPointLights( const QList<QgsPointLightSettings> &pointLights );
/**
* Sets list of directional lights defined in the scene
* \since QGIS 3.16
*/
void setDirectionalLights( const QList<QgsDirectionalLightSettings> &pointLights );
/** /**
* Returns the camera lens' field of view * Returns the camera lens' field of view
* \since QGIS 3.8 * \since QGIS 3.8
@ -413,6 +426,12 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
*/ */
void pointLightsChanged(); void pointLightsChanged();
/**
* Emitted when the list of directional lights changes
* \since QGIS 3.16
*/
void directionalLightsChanged();
/** /**
* Emitted when the camera lens field of view changes * Emitted when the camera lens field of view changes
* \since QGIS 3.8 * \since QGIS 3.8
@ -442,7 +461,8 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
bool mShowTerrainTileInfo = false; //!< Whether to draw extra information about terrain tiles to the textures - useful for debugging bool mShowTerrainTileInfo = false; //!< Whether to draw extra information about terrain tiles to the textures - useful for debugging
bool mShowCameraViewCenter = false; //!< Whether to show camera view center as a sphere - useful for debugging bool mShowCameraViewCenter = false; //!< Whether to show camera view center as a sphere - useful for debugging
bool mShowLabels = false; //!< Whether to display labels on terrain tiles bool mShowLabels = false; //!< Whether to display labels on terrain tiles
QList<QgsPointLightSettings> mPointLights; //!< List of lights defined for the scene QList<QgsPointLightSettings> mPointLights; //!< List of point lights defined for the scene
QList<QgsDirectionalLightSettings> mDirectionalLights; //!< List of directional lights defined for the scene
float mFieldOfView = 45.0f; //<! Camera lens field of view value float mFieldOfView = 45.0f; //<! Camera lens field of view value
QList<QgsMapLayerRef> mLayers; //!< Layers to be rendered QList<QgsMapLayerRef> mLayers; //!< Layers to be rendered
QList<QgsAbstract3DRenderer *> mRenderers; //!< Extra stuff to render as 3D object QList<QgsAbstract3DRenderer *> mRenderers; //!< Extra stuff to render as 3D object

View File

@ -0,0 +1,46 @@
/***************************************************************************
qgsdirectionallightsettings.cpp
--------------------------------------
Date : June 2020
Copyright : (C) 2020 by Belgacem Nedjima
Email : gb underscore nedjima at esi dot dz
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsdirectionallightsettings.h"
#include <QDomDocument>
#include "qgssymbollayerutils.h"
QDomElement QgsDirectionalLightSettings::writeXml( QDomDocument &doc ) const
{
QDomElement elemLight = doc.createElement( QStringLiteral( "directional-light" ) );
elemLight.setAttribute( QStringLiteral( "x" ), mDirection.x() );
elemLight.setAttribute( QStringLiteral( "y" ), mDirection.y() );
elemLight.setAttribute( QStringLiteral( "z" ), mDirection.z() );
elemLight.setAttribute( QStringLiteral( "color" ), QgsSymbolLayerUtils::encodeColor( mColor ) );
elemLight.setAttribute( QStringLiteral( "intensity" ), mIntensity );
return elemLight;
}
void QgsDirectionalLightSettings::readXml( const QDomElement &elem )
{
mDirection.set( elem.attribute( QStringLiteral( "x" ) ).toFloat(),
elem.attribute( QStringLiteral( "y" ) ).toFloat(),
elem.attribute( QStringLiteral( "z" ) ).toFloat() );
mColor = QgsSymbolLayerUtils::decodeColor( elem.attribute( QStringLiteral( "color" ) ) );
mIntensity = elem.attribute( QStringLiteral( "intensity" ) ).toFloat();
}
bool QgsDirectionalLightSettings::operator==( const QgsDirectionalLightSettings &other )
{
return mDirection == other.mDirection && mColor == other.mColor && mIntensity == other.mIntensity;
}

View File

@ -0,0 +1,66 @@
#ifndef QGSDIRECTIONALLIGHTSETTINGS_H
#define QGSDIRECTIONALLIGHTSETTINGS_H
/***************************************************************************
qgsdirectionallightsettings.h
--------------------------------------
Date : June 2020
Copyright : (C) 2020 by Belgacem Nedjima
Email : gb underscore nedjima at esi dot dz
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgis_3d.h"
#include "qgsvector3d.h"
#include <QColor>
class QDomDocument;
class QDomElement;
/**
* \ingroup 3d
* Definition of a directional light in a 3D map scene
*
* \since QGIS 3.16
*/
class _3D_EXPORT QgsDirectionalLightSettings
{
public:
//! Construct a directional light with default values
QgsDirectionalLightSettings() = default;
//! Returns the direction of the light in degrees
QgsVector3D direction() const { return mDirection; }
//! Sets the direction of the light in degrees
void setDirection( const QgsVector3D &direction ) { mDirection = direction; }
//! Returns color of the light
QColor color() const { return mColor; }
//! Sets color of the light
void setColor( const QColor &color ) { mColor = color; }
//! Returns intensity of the light
float intensity() const { return mIntensity; }
//! Sets intensity of the light
void setIntensity( float intensity ) { mIntensity = intensity; }
//! Writes configuration to a new DOM element and returns it
QDomElement writeXml( QDomDocument &doc ) const;
//! Reads configuration from a DOM element previously written using writeXml()
void readXml( const QDomElement &elem );
bool operator==( const QgsDirectionalLightSettings &other );
private:
QgsVector3D mDirection = QgsVector3D( 0.0, -1.0, 0.0 );
QColor mColor = Qt::white;
float mIntensity = 0.5;
};
#endif // QGSDIRECTIONALLIGHTSETTINGS_H

View File

@ -108,6 +108,7 @@ Qgs3DMapConfigWidget::Qgs3DMapConfigWidget( Qgs3DMapSettings *map, QgsMapCanvas
widgetTerrainMaterial->setMaterial( mMap->terrainShadingMaterial() ); widgetTerrainMaterial->setMaterial( mMap->terrainShadingMaterial() );
widgetLights->setPointLights( mMap->pointLights() ); widgetLights->setPointLights( mMap->pointLights() );
widgetLights->setDirectionalLights( mMap->directionalLights() );
connect( cboTerrainType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &Qgs3DMapConfigWidget::onTerrainTypeChanged ); connect( cboTerrainType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &Qgs3DMapConfigWidget::onTerrainTypeChanged );
connect( cboTerrainLayer, static_cast<void ( QComboBox::* )( int )>( &QgsMapLayerComboBox::currentIndexChanged ), this, &Qgs3DMapConfigWidget::onTerrainLayerChanged ); connect( cboTerrainLayer, static_cast<void ( QComboBox::* )( int )>( &QgsMapLayerComboBox::currentIndexChanged ), this, &Qgs3DMapConfigWidget::onTerrainLayerChanged );
@ -226,6 +227,7 @@ void Qgs3DMapConfigWidget::apply()
mMap->setTerrainShadingMaterial( widgetTerrainMaterial->material() ); mMap->setTerrainShadingMaterial( widgetTerrainMaterial->material() );
mMap->setPointLights( widgetLights->pointLights() ); mMap->setPointLights( widgetLights->pointLights() );
mMap->setDirectionalLights( widgetLights->directionalLights() );
} }
void Qgs3DMapConfigWidget::onTerrainTypeChanged() void Qgs3DMapConfigWidget::onTerrainTypeChanged()

View File

@ -41,6 +41,19 @@ QgsLightsWidget::QgsLightsWidget( QWidget *parent )
connect( spinA0, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsLightsWidget::updateCurrentLightParameters ); connect( spinA0, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsLightsWidget::updateCurrentLightParameters );
connect( spinA1, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsLightsWidget::updateCurrentLightParameters ); connect( spinA1, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsLightsWidget::updateCurrentLightParameters );
connect( spinA2, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsLightsWidget::updateCurrentLightParameters ); connect( spinA2, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsLightsWidget::updateCurrentLightParameters );
btnAddDirectionalLight->setIcon( QIcon( QgsApplication::iconPath( "symbologyAdd.svg" ) ) );
btnRemoveDirectionalLight->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.svg" ) ) );
connect( btnAddDirectionalLight, &QToolButton::clicked, this, &QgsLightsWidget::onAddDirectionalLight );
connect( btnRemoveDirectionalLight, &QToolButton::clicked, this, &QgsLightsWidget::onRemoveDirectionalLight );
connect( cboDirectionalLights, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, &QgsLightsWidget::onCurrentDirectionalLightChanged );
connect( spinDirectionX, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsLightsWidget::updateCurrentDirectionalLightParameters );
connect( spinDirectionY, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsLightsWidget::updateCurrentDirectionalLightParameters );
connect( spinDirectionZ, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsLightsWidget::updateCurrentDirectionalLightParameters );
connect( spinDirectionalIntensity, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsLightsWidget::updateCurrentDirectionalLightParameters );
connect( btnDirectionalColor, &QgsColorButton::colorChanged, this, &QgsLightsWidget::updateCurrentDirectionalLightParameters );
} }
void QgsLightsWidget::setPointLights( const QList<QgsPointLightSettings> &pointLights ) void QgsLightsWidget::setPointLights( const QList<QgsPointLightSettings> &pointLights )
@ -51,11 +64,24 @@ void QgsLightsWidget::setPointLights( const QList<QgsPointLightSettings> &pointL
onCurrentLightChanged( 0 ); onCurrentLightChanged( 0 );
} }
void QgsLightsWidget::setDirectionalLights( const QList<QgsDirectionalLightSettings> &directionalLights )
{
mDirectionalLights = directionalLights;
updateDirectionalLightsList();
cboDirectionalLights->setCurrentIndex( 0 );
onCurrentDirectionalLightChanged( 0 );
}
QList<QgsPointLightSettings> QgsLightsWidget::pointLights() QList<QgsPointLightSettings> QgsLightsWidget::pointLights()
{ {
return mPointLights; return mPointLights;
} }
QList<QgsDirectionalLightSettings> QgsLightsWidget::directionalLights()
{
return mDirectionalLights;
}
void QgsLightsWidget::onCurrentLightChanged( int index ) void QgsLightsWidget::onCurrentLightChanged( int index )
{ {
if ( index < 0 || index >= cboLights->count() ) if ( index < 0 || index >= cboLights->count() )
@ -72,6 +98,20 @@ void QgsLightsWidget::onCurrentLightChanged( int index )
whileBlocking( spinA2 )->setValue( light.quadraticAttenuation() ); whileBlocking( spinA2 )->setValue( light.quadraticAttenuation() );
} }
void QgsLightsWidget::onCurrentDirectionalLightChanged( int index )
{
if ( index < 0 || index >= cboDirectionalLights->count() )
return;
QgsDirectionalLightSettings light = mDirectionalLights.at( index );
whileBlocking( spinDirectionX )->setValue( light.direction().x() );
whileBlocking( spinDirectionY )->setValue( light.direction().y() );
whileBlocking( spinDirectionZ )->setValue( light.direction().z() );
whileBlocking( btnDirectionalColor )->setColor( light.color() );
whileBlocking( spinDirectionalIntensity )->setValue( light.intensity() );
}
void QgsLightsWidget::updateCurrentLightParameters() void QgsLightsWidget::updateCurrentLightParameters()
{ {
int index = cboLights->currentIndex(); int index = cboLights->currentIndex();
@ -88,6 +128,19 @@ void QgsLightsWidget::updateCurrentLightParameters()
mPointLights[index] = light; mPointLights[index] = light;
} }
void QgsLightsWidget::updateCurrentDirectionalLightParameters()
{
int index = cboDirectionalLights->currentIndex();
if ( index < 0 || index >= cboDirectionalLights->count() )
return;
QgsDirectionalLightSettings light;
light.setDirection( QgsVector3D( spinDirectionX->value(), spinDirectionY->value(), spinDirectionZ->value() ) );
light.setColor( btnDirectionalColor->color() );
light.setIntensity( spinDirectionalIntensity->value() );
mDirectionalLights[index] = light;
}
void QgsLightsWidget::onAddLight() void QgsLightsWidget::onAddLight()
{ {
if ( mPointLights.count() >= 8 ) if ( mPointLights.count() >= 8 )
@ -99,6 +152,23 @@ void QgsLightsWidget::onAddLight()
mPointLights << QgsPointLightSettings(); mPointLights << QgsPointLightSettings();
updateLightsList(); updateLightsList();
cboLights->setCurrentIndex( cboLights->count() - 1 ); cboLights->setCurrentIndex( cboLights->count() - 1 );
// To set default parameters of the light
onCurrentDirectionalLightChanged( 0 );
}
void QgsLightsWidget::onAddDirectionalLight()
{
if ( mDirectionalLights.count() >= 4 )
{
QMessageBox::warning( this, tr( "Add Directional Light" ), tr( "It is not possible to add more than 4 directional lights to the scene." ) );
return;
}
mDirectionalLights << QgsDirectionalLightSettings();
updateDirectionalLightsList();
cboDirectionalLights->setCurrentIndex( cboDirectionalLights->count() - 1 );
// To set default parameters of the light
onCurrentDirectionalLightChanged( 0 );
} }
void QgsLightsWidget::onRemoveLight() void QgsLightsWidget::onRemoveLight()
@ -115,6 +185,20 @@ void QgsLightsWidget::onRemoveLight()
onCurrentLightChanged( index ); onCurrentLightChanged( index );
} }
void QgsLightsWidget::onRemoveDirectionalLight()
{
int index = cboDirectionalLights->currentIndex();
if ( index < 0 || index >= cboDirectionalLights->count() )
return;
mDirectionalLights.removeAt( index );
updateDirectionalLightsList();
if ( index >= cboDirectionalLights->count() )
--index; // in case we removed the last light
cboDirectionalLights->setCurrentIndex( index );
onCurrentDirectionalLightChanged( index );
}
void QgsLightsWidget::updateLightsList() void QgsLightsWidget::updateLightsList()
{ {
cboLights->blockSignals( true ); cboLights->blockSignals( true );
@ -125,3 +209,14 @@ void QgsLightsWidget::updateLightsList()
} }
cboLights->blockSignals( false ); cboLights->blockSignals( false );
} }
void QgsLightsWidget::updateDirectionalLightsList()
{
cboDirectionalLights->blockSignals( true );
cboDirectionalLights->clear();
for ( int i = 0; i < mDirectionalLights.count(); ++i )
{
cboDirectionalLights->addItem( tr( "Directional light %1" ).arg( i + 1 ) );
}
cboDirectionalLights->blockSignals( false );
}

View File

@ -21,6 +21,7 @@
#include "ui_qgslightswidget.h" #include "ui_qgslightswidget.h"
#include "qgspointlightsettings.h" #include "qgspointlightsettings.h"
#include "qgsdirectionallightsettings.h"
/** /**
@ -34,8 +35,10 @@ class QgsLightsWidget : public QWidget, private Ui::QgsLightsWidget
explicit QgsLightsWidget( QWidget *parent = nullptr ); explicit QgsLightsWidget( QWidget *parent = nullptr );
void setPointLights( const QList<QgsPointLightSettings> &pointLights ); void setPointLights( const QList<QgsPointLightSettings> &pointLights );
void setDirectionalLights( const QList<QgsDirectionalLightSettings> &directionalLights );
QList<QgsPointLightSettings> pointLights(); QList<QgsPointLightSettings> pointLights();
QList<QgsDirectionalLightSettings> directionalLights();
signals: signals:
@ -45,11 +48,18 @@ class QgsLightsWidget : public QWidget, private Ui::QgsLightsWidget
void onAddLight(); void onAddLight();
void onRemoveLight(); void onRemoveLight();
void onCurrentDirectionalLightChanged( int index );
void updateCurrentDirectionalLightParameters();
void onAddDirectionalLight();
void onRemoveDirectionalLight();
private: private:
void updateLightsList(); void updateLightsList();
void updateDirectionalLightsList();
private: private:
QList<QgsPointLightSettings> mPointLights; QList<QgsPointLightSettings> mPointLights;
QList<QgsDirectionalLightSettings> mDirectionalLights;
}; };
#endif // QGSLIGHTSWIDGET_H #endif // QGSLIGHTSWIDGET_H

View File

@ -15,187 +15,349 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <widget class="QTabWidget" name="tabWidget">
<item> <property name="currentIndex">
<widget class="QComboBox" name="cboLights"/> <number>0</number>
</item> </property>
<item> <widget class="QWidget" name="tab">
<widget class="QToolButton" name="btnAddLight"> <attribute name="title">
<property name="text"> <string>Point lights</string>
<string>...</string> </attribute>
</property> <layout class="QGridLayout" name="gridLayout_2">
</widget> <item row="0" column="0">
</item> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="QToolButton" name="btnRemoveLight"> <widget class="QComboBox" name="cboLights"/>
<property name="text"> </item>
<string>...</string> <item>
</property> <widget class="QToolButton" name="btnAddLight">
</widget> <property name="text">
</item> <string>...</string>
</layout> </property>
</item> </widget>
<item> </item>
<layout class="QGridLayout" name="gridLayout"> <item>
<item row="7" column="1"> <widget class="QToolButton" name="btnRemoveLight">
<widget class="QDoubleSpinBox" name="spinA0"> <property name="text">
<property name="maximum"> <string>...</string>
<double>9.000000000000000</double> </property>
</property> </widget>
<property name="singleStep"> </item>
<double>0.100000000000000</double> </layout>
</property> </item>
</widget> <item row="1" column="0">
</item> <layout class="QGridLayout" name="gridLayout">
<item row="8" column="1"> <item row="3" column="0">
<widget class="QDoubleSpinBox" name="spinA1"> <widget class="QLabel" name="label_3">
<property name="maximum"> <property name="text">
<double>9.000000000000000</double> <string>Z</string>
</property> </property>
<property name="singleStep"> </widget>
<double>0.100000000000000</double> </item>
</property> <item row="0" column="1">
</widget> <widget class="QDoubleSpinBox" name="spinPositionX">
</item> <property name="decimals">
<item row="0" column="0"> <number>1</number>
<widget class="QLabel" name="label"> </property>
<property name="text"> <property name="minimum">
<string>X</string> <double>-9999999.000000000000000</double>
</property> </property>
</widget> <property name="maximum">
</item> <double>9999999.000000000000000</double>
<item row="3" column="0"> </property>
<widget class="QLabel" name="label_3"> </widget>
<property name="text"> </item>
<string>Z</string> <item row="9" column="0">
</property> <widget class="QLabel" name="label_9">
</widget> <property name="text">
</item> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;A&lt;span style=&quot; vertical-align:sub;&quot;&gt;2&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<item row="0" column="1"> </property>
<widget class="QDoubleSpinBox" name="spinPositionX"> </widget>
<property name="decimals"> </item>
<number>1</number> <item row="5" column="1">
</property> <widget class="QDoubleSpinBox" name="spinIntensity">
<property name="minimum"> <property name="decimals">
<double>-9999999.000000000000000</double> <number>1</number>
</property> </property>
<property name="maximum"> <property name="maximum">
<double>9999999.000000000000000</double> <double>999999.000000000000000</double>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1" rowspan="2"> <item row="7" column="0">
<widget class="QDoubleSpinBox" name="spinPositionY"> <widget class="QLabel" name="label_7">
<property name="decimals"> <property name="text">
<number>1</number> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;A&lt;span style=&quot; vertical-align:sub;&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="minimum"> </widget>
<double>-9999999.000000000000000</double> </item>
</property> <item row="1" column="1" rowspan="2">
<property name="maximum"> <widget class="QDoubleSpinBox" name="spinPositionY">
<double>9999999.000000000000000</double> <property name="decimals">
</property> <number>1</number>
</widget> </property>
</item> <property name="minimum">
<item row="1" column="0" rowspan="2"> <double>-9999999.000000000000000</double>
<widget class="QLabel" name="label_2"> </property>
<property name="text"> <property name="maximum">
<string>Y</string> <double>9999999.000000000000000</double>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="1" column="0" rowspan="2">
<widget class="QDoubleSpinBox" name="spinPositionZ"> <widget class="QLabel" name="label_2">
<property name="decimals"> <property name="text">
<number>1</number> <string>Y</string>
</property> </property>
<property name="minimum"> </widget>
<double>-9999999.000000000000000</double> </item>
</property> <item row="3" column="1">
<property name="maximum"> <widget class="QDoubleSpinBox" name="spinPositionZ">
<double>9999999.000000000000000</double> <property name="decimals">
</property> <number>1</number>
</widget> </property>
</item> <property name="minimum">
<item row="5" column="0"> <double>-9999999.000000000000000</double>
<widget class="QLabel" name="label_4"> </property>
<property name="text"> <property name="maximum">
<string>Intensity</string> <double>9999999.000000000000000</double>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="1"> <item row="4" column="1">
<widget class="QDoubleSpinBox" name="spinIntensity"> <widget class="QgsColorButton" name="btnColor">
<property name="decimals"> <property name="sizePolicy">
<number>1</number> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
</property> <horstretch>0</horstretch>
<property name="maximum"> <verstretch>0</verstretch>
<double>999999.000000000000000</double> </sizepolicy>
</property> </property>
</widget> <property name="minimumSize">
</item> <size>
<item row="6" column="0" colspan="2"> <width>120</width>
<widget class="QLabel" name="label_6"> <height>0</height>
<property name="text"> </size>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Attenuation (A&lt;span style=&quot; vertical-align:sub;&quot;&gt;0&lt;/span&gt;+A&lt;span style=&quot; vertical-align:sub;&quot;&gt;1&lt;/span&gt;*D+A&lt;span style=&quot; vertical-align:sub;&quot;&gt;2&lt;/span&gt;*D&lt;span style=&quot; vertical-align:super;&quot;&gt;2&lt;/span&gt;)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> </property>
</property> </widget>
</widget> </item>
</item> <item row="7" column="1">
<item row="4" column="1"> <widget class="QDoubleSpinBox" name="spinA0">
<widget class="QgsColorButton" name="btnColor"> <property name="maximum">
<property name="sizePolicy"> <double>9.000000000000000</double>
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> </property>
<horstretch>0</horstretch> <property name="singleStep">
<verstretch>0</verstretch> <double>0.100000000000000</double>
</sizepolicy> </property>
</property> </widget>
<property name="minimumSize"> </item>
<size> <item row="8" column="1">
<width>120</width> <widget class="QDoubleSpinBox" name="spinA1">
<height>0</height> <property name="maximum">
</size> <double>9.000000000000000</double>
</property> </property>
</widget> <property name="singleStep">
</item> <double>0.100000000000000</double>
<item row="4" column="0"> </property>
<widget class="QLabel" name="label_5"> </widget>
<property name="text"> </item>
<string>Color</string> <item row="9" column="1">
</property> <widget class="QDoubleSpinBox" name="spinA2">
</widget> <property name="maximum">
</item> <double>9.000000000000000</double>
<item row="9" column="1"> </property>
<widget class="QDoubleSpinBox" name="spinA2"> <property name="singleStep">
<property name="maximum"> <double>0.100000000000000</double>
<double>9.000000000000000</double> </property>
</property> </widget>
<property name="singleStep"> </item>
<double>0.100000000000000</double> <item row="5" column="0">
</property> <widget class="QLabel" name="label_4">
</widget> <property name="text">
</item> <string>Intensity</string>
<item row="7" column="0"> </property>
<widget class="QLabel" name="label_7"> </widget>
<property name="text"> </item>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;A&lt;span style=&quot; vertical-align:sub;&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <item row="8" column="0">
</property> <widget class="QLabel" name="label_8">
</widget> <property name="text">
</item> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;A&lt;span style=&quot; vertical-align:sub;&quot;&gt;1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<item row="8" column="0"> </property>
<widget class="QLabel" name="label_8"> </widget>
<property name="text"> </item>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;A&lt;span style=&quot; vertical-align:sub;&quot;&gt;1&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <item row="4" column="0">
</property> <widget class="QLabel" name="label_5">
</widget> <property name="text">
</item> <string>Color</string>
<item row="9" column="0"> </property>
<widget class="QLabel" name="label_9"> </widget>
<property name="text"> </item>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;A&lt;span style=&quot; vertical-align:sub;&quot;&gt;2&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <item row="0" column="0">
</property> <widget class="QLabel" name="label">
</widget> <property name="text">
</item> <string>X</string>
</layout> </property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Attenuation (A&lt;span style=&quot; vertical-align:sub;&quot;&gt;0&lt;/span&gt;+A&lt;span style=&quot; vertical-align:sub;&quot;&gt;1&lt;/span&gt;*D+A&lt;span style=&quot; vertical-align:sub;&quot;&gt;2&lt;/span&gt;*D&lt;span style=&quot; vertical-align:super;&quot;&gt;2&lt;/span&gt;)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Directional lights</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="1" column="0" colspan="3">
<layout class="QGridLayout" name="gridLayout_3">
<item row="4" column="1">
<widget class="QDoubleSpinBox" name="spinDirectionZ">
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>-9999999.000000000000000</double>
</property>
<property name="maximum">
<double>9999999.000000000000000</double>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QgsColorButton" name="btnDirectionalColor">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Intensity</string>
</property>
</widget>
</item>
<item row="2" column="0" rowspan="2">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Y</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Z</string>
</property>
</widget>
</item>
<item row="2" column="1" rowspan="2">
<widget class="QDoubleSpinBox" name="spinDirectionY">
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>-9999999.000000000000000</double>
</property>
<property name="maximum">
<double>9999999.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="spinDirectionX">
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>-9999999.000000000000000</double>
</property>
<property name="maximum">
<double>9999999.000000000000000</double>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QDoubleSpinBox" name="spinDirectionalIntensity">
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Color</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Light direction:</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="btnRemoveDirectionalLight">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QToolButton" name="btnAddDirectionalLight">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QComboBox" name="cboDirectionalLights"/>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>
@ -208,7 +370,6 @@
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>cboLights</tabstop>
<tabstop>btnAddLight</tabstop> <tabstop>btnAddLight</tabstop>
<tabstop>btnRemoveLight</tabstop> <tabstop>btnRemoveLight</tabstop>
<tabstop>spinPositionX</tabstop> <tabstop>spinPositionX</tabstop>