|
@@ -32,36 +32,131 @@ |
|
|
PointEntity::PointEntity( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol, Qt3DCore::QNode *parent ) |
|
|
: Qt3DCore::QEntity( parent ) |
|
|
{ |
|
|
QgsFeatureRequest request; |
|
|
request.setDestinationCrs( map.crs ); |
|
|
QList<QVector3D> pos = positions( map, layer, request ); |
|
|
addEntityForSelectedPoints( map, layer, symbol ); |
|
|
addEntityForNotSelectedPoints( map, layer, symbol ); |
|
|
} |
|
|
|
|
|
addComponent( renderer( symbol, pos ) ); |
|
|
addComponent( material( map, symbol ) ); |
|
|
Qt3DRender::QMaterial *PointEntity::material( const Point3DSymbol &symbol ) const |
|
|
{ |
|
|
Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey; |
|
|
filterKey->setName( "renderingStyle" ); |
|
|
filterKey->setValue( "forward" ); |
|
|
|
|
|
// the fragment shader implements a simplified version of phong shading that uses hardcoded light |
|
|
// (instead of whatever light we have defined in the scene) |
|
|
// TODO: use phong shading that respects lights from the scene |
|
|
Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram; |
|
|
shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( "qrc:/shaders/instanced.vert" ) ) ); |
|
|
shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( "qrc:/shaders/instanced.frag" ) ) ); |
|
|
|
|
|
Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass; |
|
|
renderPass->setShaderProgram( shaderProgram ); |
|
|
|
|
|
Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique; |
|
|
technique->addFilterKey( filterKey ); |
|
|
technique->addRenderPass( renderPass ); |
|
|
technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL ); |
|
|
technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile ); |
|
|
technique->graphicsApiFilter()->setMajorVersion( 3 ); |
|
|
technique->graphicsApiFilter()->setMinorVersion( 2 ); |
|
|
|
|
|
Qt3DRender::QParameter *ambientParameter = new Qt3DRender::QParameter( QStringLiteral( "ka" ), QColor::fromRgbF( 0.05f, 0.05f, 0.05f, 1.0f ) ); |
|
|
Qt3DRender::QParameter *diffuseParameter = new Qt3DRender::QParameter( QStringLiteral( "kd" ), QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) ); |
|
|
Qt3DRender::QParameter *specularParameter = new Qt3DRender::QParameter( QStringLiteral( "ks" ), QColor::fromRgbF( 0.01f, 0.01f, 0.01f, 1.0f ) ); |
|
|
Qt3DRender::QParameter *shininessParameter = new Qt3DRender::QParameter( QStringLiteral( "shininess" ), 150.0f ); |
|
|
|
|
|
diffuseParameter->setValue( symbol.material.diffuse() ); |
|
|
ambientParameter->setValue( symbol.material.ambient() ); |
|
|
specularParameter->setValue( symbol.material.specular() ); |
|
|
shininessParameter->setValue( symbol.material.shininess() ); |
|
|
|
|
|
QMatrix4x4 transformMatrix = symbol.transform; |
|
|
QMatrix3x3 normalMatrix = transformMatrix.normalMatrix(); // transponed inverse of 3x3 sub-matrix |
|
|
|
|
|
// QMatrix3x3 is not supported for passing to shaders, so we pass QMatrix4x4 |
|
|
float *n = normalMatrix.data(); |
|
|
QMatrix4x4 normalMatrix4( |
|
|
n[0], n[3], n[6], 0, |
|
|
n[1], n[4], n[7], 0, |
|
|
n[2], n[5], n[8], 0, |
|
|
0, 0, 0, 0 ); |
|
|
|
|
|
Qt3DRender::QParameter *paramInst = new Qt3DRender::QParameter; |
|
|
paramInst->setName( "inst" ); |
|
|
paramInst->setValue( transformMatrix ); |
|
|
|
|
|
Qt3DRender::QParameter *paramInstNormal = new Qt3DRender::QParameter; |
|
|
paramInstNormal->setName( "instNormal" ); |
|
|
paramInstNormal->setValue( normalMatrix4 ); |
|
|
|
|
|
Qt3DRender::QEffect *effect = new Qt3DRender::QEffect; |
|
|
effect->addTechnique( technique ); |
|
|
effect->addParameter( paramInst ); |
|
|
effect->addParameter( paramInstNormal ); |
|
|
|
|
|
effect->addParameter( ambientParameter ); |
|
|
effect->addParameter( diffuseParameter ); |
|
|
effect->addParameter( specularParameter ); |
|
|
effect->addParameter( shininessParameter ); |
|
|
|
|
|
Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial; |
|
|
material->setEffect( effect ); |
|
|
|
|
|
return material; |
|
|
} |
|
|
|
|
|
PointEntity::PointEntity( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol, bool sel, Qt3DCore::QNode *parent ) |
|
|
: Qt3DCore::QEntity( parent ) |
|
|
void PointEntity::addEntityForSelectedPoints( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol ) |
|
|
{ |
|
|
QgsFeatureRequest request; |
|
|
request.setDestinationCrs( map.crs ); |
|
|
// build the default material |
|
|
Qt3DRender::QMaterial *mat = material( symbol ); |
|
|
|
|
|
if ( sel ) |
|
|
request.setFilterFids( layer->selectedFeatureIds() ); |
|
|
else |
|
|
// update the material with selection colors |
|
|
Q_FOREACH ( Qt3DRender::QParameter *param, mat->effect()->parameters() ) |
|
|
{ |
|
|
QgsFeatureIds notSelected = layer->allFeatureIds(); |
|
|
notSelected.subtract( layer->selectedFeatureIds() ); |
|
|
request.setFilterFids( notSelected ); |
|
|
if ( param->name() == "kd" ) // diffuse |
|
|
param->setValue( map.selectionColor() ); |
|
|
else if ( param->name() == "ka" ) // ambient |
|
|
param->setValue( map.selectionColor().darker() ); |
|
|
} |
|
|
|
|
|
QList<QVector3D> pos = positions( map, layer, request ); |
|
|
// build the feature request to select features |
|
|
QgsFeatureRequest req; |
|
|
req.setDestinationCrs( map.crs ); |
|
|
req.setFilterFids( layer->selectedFeatureIds() ); |
|
|
|
|
|
// build the entity |
|
|
PointEntityNode *entity = new PointEntityNode( map, layer, symbol, req ); |
|
|
entity->addComponent( mat ); |
|
|
entity->setParent( this ); |
|
|
} |
|
|
|
|
|
void PointEntity::addEntityForNotSelectedPoints( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol ) |
|
|
{ |
|
|
// build the default material |
|
|
Qt3DRender::QMaterial *mat = material( symbol ); |
|
|
|
|
|
// build the feature request to select features |
|
|
QgsFeatureRequest req; |
|
|
req.setDestinationCrs( map.crs ); |
|
|
|
|
|
QgsFeatureIds notSelected = layer->allFeatureIds(); |
|
|
notSelected.subtract( layer->selectedFeatureIds() ); |
|
|
req.setFilterFids( notSelected ); |
|
|
|
|
|
// build the entity |
|
|
PointEntityNode *entity = new PointEntityNode( map, layer, symbol, req ); |
|
|
entity->addComponent( mat ); |
|
|
entity->setParent( this ); |
|
|
} |
|
|
|
|
|
PointEntityNode::PointEntityNode( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol, const QgsFeatureRequest &req, Qt3DCore::QNode *parent ) |
|
|
: Qt3DCore::QEntity( parent ) |
|
|
{ |
|
|
QList<QVector3D> pos = positions( map, layer, req ); |
|
|
addComponent( renderer( symbol, pos ) ); |
|
|
addComponent( material( map, symbol, sel ) ); |
|
|
} |
|
|
|
|
|
Qt3DRender::QGeometryRenderer *PointEntity::renderer( const Point3DSymbol &symbol, const QList<QVector3D> &positions ) const |
|
|
Qt3DRender::QGeometryRenderer *PointEntityNode::renderer( const Point3DSymbol &symbol, const QList<QVector3D> &positions ) const |
|
|
{ |
|
|
int count = positions.count(); |
|
|
|
|
@@ -168,82 +263,7 @@ Qt3DRender::QGeometryRenderer *PointEntity::renderer( const Point3DSymbol &symbo |
|
|
return renderer; |
|
|
} |
|
|
|
|
|
Qt3DRender::QMaterial *PointEntity::material( const Map3D &map, const Point3DSymbol &symbol, bool sel ) const |
|
|
{ |
|
|
Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey; |
|
|
filterKey->setName( "renderingStyle" ); |
|
|
filterKey->setValue( "forward" ); |
|
|
|
|
|
// the fragment shader implements a simplified version of phong shading that uses hardcoded light |
|
|
// (instead of whatever light we have defined in the scene) |
|
|
// TODO: use phong shading that respects lights from the scene |
|
|
Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram; |
|
|
shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( "qrc:/shaders/instanced.vert" ) ) ); |
|
|
shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( "qrc:/shaders/instanced.frag" ) ) ); |
|
|
|
|
|
Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass; |
|
|
renderPass->setShaderProgram( shaderProgram ); |
|
|
|
|
|
Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique; |
|
|
technique->addFilterKey( filterKey ); |
|
|
technique->addRenderPass( renderPass ); |
|
|
technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL ); |
|
|
technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile ); |
|
|
technique->graphicsApiFilter()->setMajorVersion( 3 ); |
|
|
technique->graphicsApiFilter()->setMinorVersion( 2 ); |
|
|
|
|
|
Qt3DRender::QParameter *ambientParameter = new Qt3DRender::QParameter( QStringLiteral( "ka" ), QColor::fromRgbF( 0.05f, 0.05f, 0.05f, 1.0f ) ); |
|
|
Qt3DRender::QParameter *diffuseParameter = new Qt3DRender::QParameter( QStringLiteral( "kd" ), QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) ); |
|
|
Qt3DRender::QParameter *specularParameter = new Qt3DRender::QParameter( QStringLiteral( "ks" ), QColor::fromRgbF( 0.01f, 0.01f, 0.01f, 1.0f ) ); |
|
|
Qt3DRender::QParameter *shininessParameter = new Qt3DRender::QParameter( QStringLiteral( "shininess" ), 150.0f ); |
|
|
|
|
|
diffuseParameter->setValue( symbol.material.diffuse() ); |
|
|
ambientParameter->setValue( symbol.material.ambient() ); |
|
|
specularParameter->setValue( symbol.material.specular() ); |
|
|
shininessParameter->setValue( symbol.material.shininess() ); |
|
|
|
|
|
if ( sel ) |
|
|
{ |
|
|
diffuseParameter->setValue( map.selectionColor() ); |
|
|
ambientParameter->setValue( map.selectionColor().darker() ); |
|
|
} |
|
|
|
|
|
QMatrix4x4 transformMatrix = symbol.transform; |
|
|
QMatrix3x3 normalMatrix = transformMatrix.normalMatrix(); // transponed inverse of 3x3 sub-matrix |
|
|
|
|
|
// QMatrix3x3 is not supported for passing to shaders, so we pass QMatrix4x4 |
|
|
float *n = normalMatrix.data(); |
|
|
QMatrix4x4 normalMatrix4( |
|
|
n[0], n[3], n[6], 0, |
|
|
n[1], n[4], n[7], 0, |
|
|
n[2], n[5], n[8], 0, |
|
|
0, 0, 0, 0 ); |
|
|
|
|
|
Qt3DRender::QParameter *paramInst = new Qt3DRender::QParameter; |
|
|
paramInst->setName( "inst" ); |
|
|
paramInst->setValue( transformMatrix ); |
|
|
|
|
|
Qt3DRender::QParameter *paramInstNormal = new Qt3DRender::QParameter; |
|
|
paramInstNormal->setName( "instNormal" ); |
|
|
paramInstNormal->setValue( normalMatrix4 ); |
|
|
|
|
|
Qt3DRender::QEffect *effect = new Qt3DRender::QEffect; |
|
|
effect->addTechnique( technique ); |
|
|
effect->addParameter( paramInst ); |
|
|
effect->addParameter( paramInstNormal ); |
|
|
|
|
|
effect->addParameter( ambientParameter ); |
|
|
effect->addParameter( diffuseParameter ); |
|
|
effect->addParameter( specularParameter ); |
|
|
effect->addParameter( shininessParameter ); |
|
|
|
|
|
Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial; |
|
|
material->setEffect( effect ); |
|
|
|
|
|
return material; |
|
|
} |
|
|
|
|
|
QList<QVector3D> PointEntity::positions( const Map3D &map, const QgsVectorLayer *layer, const QgsFeatureRequest &request ) const |
|
|
QList<QVector3D> PointEntityNode::positions( const Map3D &map, const QgsVectorLayer *layer, const QgsFeatureRequest &request ) const |
|
|
{ |
|
|
QList<QVector3D> positions; |
|
|
QgsFeature f; |
|
|