Skip to content
Permalink
Browse files

[Feature] directional lights support for QGIS 3D

  • Loading branch information
NEDJIMAbelgacem authored and nyalldawson committed Jun 6, 2020
1 parent 672d6ec commit 9556bd2147420a07aa3ce22fabd3f1aae027a034
@@ -7,6 +7,7 @@
%Include auto_generated/qgslayoutitem3dmap.sip
%Include auto_generated/qgsphongmaterialsettings.sip
%Include auto_generated/qgspointlightsettings.sip
%Include auto_generated/qgsdirectionallightsettings.sip
%Include auto_generated/qgsrulebased3drenderer.sip
%Include auto_generated/qgsvectorlayer3drenderer.sip
%Include auto_generated/symbols/qgsabstract3dsymbol.sip
@@ -366,13 +366,27 @@ Returns whether to display labels on terrain tiles
Returns list of point lights defined in the scene

.. versionadded:: 3.6
%End

QList<QgsDirectionalLightSettings> directionalLights() const;
%Docstring
Returns list of directional lights defined in the scene

.. versionadded:: 3.16
%End

void setPointLights( const QList<QgsPointLightSettings> &pointLights );
%Docstring
Sets list of point lights defined in the scene

.. versionadded:: 3.6
%End

void setDirectionalLights( const QList<QgsDirectionalLightSettings> &pointLights );
%Docstring
Sets list of directional lights defined in the scene

.. versionadded:: 3.16
%End

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

.. versionadded:: 3.6
%End

void directionalLightsChanged();
%Docstring
Emitted when the list of directional lights changes

.. versionadded:: 3.16
%End

void fieldOfViewChanged();
@@ -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 *
************************************************************************/
@@ -16,6 +16,7 @@ SET(QGIS_3D_SRCS
qgsoffscreen3dengine.cpp
qgsphongmaterialsettings.cpp
qgspointlightsettings.cpp
qgsdirectionallightsettings.cpp
qgsraycastingutils_p.cpp
qgsrulebased3drenderer.cpp
qgsrulebasedchunkloader_p.cpp
@@ -87,6 +88,7 @@ SET(QGIS_3D_HDRS
qgsoffscreen3dengine.h
qgsphongmaterialsettings.h
qgspointlightsettings.h
qgsdirectionallightsettings.h
qgsrulebased3drenderer.h
qgstessellatedpolygongeometry.h
qgstilingscheme.h
@@ -22,6 +22,7 @@
#include <Qt3DRender/QPickingSettings>
#include <Qt3DRender/QPickTriangleEvent>
#include <Qt3DRender/QPointLight>
#include <Qt3DRender/QDirectionalLight>
#include <Qt3DRender/QRenderSettings>
#include <Qt3DRender/QSceneLoader>
#include <Qt3DExtras/QForwardRenderer>
@@ -103,6 +104,7 @@ Qgs3DMapScene::Qgs3DMapScene( const Qgs3DMapSettings &map, QgsAbstract3DEngine *
connect( &map, &Qgs3DMapSettings::maxTerrainGroundErrorChanged, this, &Qgs3DMapScene::createTerrain );
connect( &map, &Qgs3DMapSettings::terrainShadingChanged, this, &Qgs3DMapScene::createTerrain );
connect( &map, &Qgs3DMapSettings::pointLightsChanged, this, &Qgs3DMapScene::updateLights );
connect( &map, &Qgs3DMapSettings::directionalLightsChanged, this, &Qgs3DMapScene::updateLights );
connect( &map, &Qgs3DMapSettings::fieldOfViewChanged, this, &Qgs3DMapScene::updateCameraLens );
connect( &map, &Qgs3DMapSettings::renderersChanged, this, &Qgs3DMapScene::onRenderersChanged );

@@ -474,6 +476,24 @@ void Qgs3DMapScene::updateLights()
lightEntity->setParent( this );
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()
@@ -49,6 +49,7 @@ Qgs3DMapSettings::Qgs3DMapSettings( const Qgs3DMapSettings &other )
, mShowCameraViewCenter( other.mShowCameraViewCenter )
, mShowLabels( other.mShowLabels )
, mPointLights( other.mPointLights )
, mDirectionalLights( other.mDirectionalLights )
, mFieldOfView( other.mFieldOfView )
, mLayers( other.mLayers )
, mRenderers() // initialized in body
@@ -127,6 +128,20 @@ void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteConte
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 elemMapLayer = elemMapLayers.firstChildElement( QStringLiteral( "layer" ) );
QList<QgsMapLayerRef> mapLayers;
@@ -250,6 +265,14 @@ QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteCon
}
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" ) );
Q_FOREACH ( const QgsMapLayerRef &layerRef, mLayers )
{
@@ -535,6 +558,15 @@ void Qgs3DMapSettings::setPointLights( const QList<QgsPointLightSettings> &point
emit pointLightsChanged();
}

void Qgs3DMapSettings::setDirectionalLights( const QList<QgsDirectionalLightSettings> &directionalLights )
{
if ( mDirectionalLights == directionalLights )
return;

mDirectionalLights = directionalLights;
emit directionalLightsChanged();
}

void Qgs3DMapSettings::setFieldOfView( const float fieldOfView )
{
if ( mFieldOfView == fieldOfView )
@@ -27,6 +27,7 @@
#include "qgsmesh3dsymbol.h"
#include "qgsphongmaterialsettings.h"
#include "qgspointlightsettings.h"
#include "qgsdirectionallightsettings.h"
#include "qgsterraingenerator.h"
#include "qgsvector3d.h"

@@ -325,12 +326,24 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
*/
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
* \since QGIS 3.6
*/
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
* \since QGIS 3.8
@@ -413,6 +426,12 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
*/
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
* \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 mShowCameraViewCenter = false; //!< Whether to show camera view center as a sphere - useful for debugging
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
QList<QgsMapLayerRef> mLayers; //!< Layers to be rendered
QList<QgsAbstract3DRenderer *> mRenderers; //!< Extra stuff to render as 3D object
@@ -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;
}

0 comments on commit 9556bd2

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