Example #1
0
void QgsBufferedLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, LineData &out, bool selected )
{
  if ( out.polygons.isEmpty() )
    return;  // nothing to show - no need to create the entity

  Qt3DExtras::QPhongMaterial *mat = _material( mSymbol );
  if ( selected )
  {
    // update the material with selection colors
    mat->setDiffuse( context.map().selectionColor() );
    mat->setAmbient( context.map().selectionColor().darker() );
  }

  QgsPointXY origin( context.map().origin().x(), context.map().origin().y() );
  QgsTessellatedPolygonGeometry *geometry = new QgsTessellatedPolygonGeometry;
  geometry->setPolygons( out.polygons, out.fids, origin, mSymbol.extrusionHeight() );

  Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
  renderer->setGeometry( geometry );

  // make entity
  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
  entity->addComponent( renderer );
  entity->addComponent( mat );
  entity->setParent( parent );

  if ( !selected )
    entity->findChild<Qt3DRender::QGeometryRenderer *>()->setObjectName( QStringLiteral( "main" ) ); // temporary measure to distinguish between "selected" and "main"
}
Example #2
0
Qt3DRender::QGeometryRenderer *QgsLine3DSymbolEntityNode::renderer( const Qgs3DMapSettings &map, const QgsLine3DSymbol &symbol, const QgsVectorLayer *layer, const QgsFeatureRequest &request )
{
  QgsPointXY origin( map.origin().x(), map.origin().y() );

  // TODO: configurable
  int nSegments = 4;
  QgsGeometry::EndCapStyle endCapStyle = QgsGeometry::CapRound;
  QgsGeometry::JoinStyle joinStyle = QgsGeometry::JoinStyleRound;
  double mitreLimit = 0;

  QList<QgsPolygon *> polygons;
  QgsFeature f;
  QgsFeatureIterator fi = layer->getFeatures( request );
  while ( fi.nextFeature( f ) )
  {
    if ( f.geometry().isNull() )
      continue;

    QgsGeometry geom = f.geometry();

    // segmentize curved geometries if necessary
    if ( QgsWkbTypes::isCurvedType( geom.constGet()->wkbType() ) )
      geom = QgsGeometry( geom.constGet()->segmentize() );

    const QgsAbstractGeometry *g = geom.constGet();

    QgsGeos engine( g );
    QgsAbstractGeometry *buffered = engine.buffer( symbol.width() / 2., nSegments, endCapStyle, joinStyle, mitreLimit ); // factory

    if ( QgsWkbTypes::flatType( buffered->wkbType() ) == QgsWkbTypes::Polygon )
    {
      QgsPolygon *polyBuffered = static_cast<QgsPolygon *>( buffered );
      Qgs3DUtils::clampAltitudes( polyBuffered, symbol.altitudeClamping(), symbol.altitudeBinding(), symbol.height(), map );
      polygons.append( polyBuffered );
    }
    else if ( QgsWkbTypes::flatType( buffered->wkbType() ) == QgsWkbTypes::MultiPolygon )
    {
      QgsMultiPolygon *mpolyBuffered = static_cast<QgsMultiPolygon *>( buffered );
      for ( int i = 0; i < mpolyBuffered->numGeometries(); ++i )
      {
        QgsAbstractGeometry *partBuffered = mpolyBuffered->geometryN( i );
        Q_ASSERT( QgsWkbTypes::flatType( partBuffered->wkbType() ) == QgsWkbTypes::Polygon );
        QgsPolygon *polyBuffered = static_cast<QgsPolygon *>( partBuffered )->clone(); // need to clone individual geometry parts
        Qgs3DUtils::clampAltitudes( polyBuffered, symbol.altitudeClamping(), symbol.altitudeBinding(), symbol.height(), map );
        polygons.append( polyBuffered );
      }
      delete buffered;
    }
  }

  mGeometry = new QgsTessellatedPolygonGeometry;
  mGeometry->setPolygons( polygons, origin, symbol.extrusionHeight() );

  Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
  renderer->setGeometry( mGeometry );

  return renderer;
}
Qt3DCore::QEntity *QgsDemTerrainTileLoader::createEntity( Qt3DCore::QEntity *parent )
{
  QgsTerrainTileEntity *entity = new QgsTerrainTileEntity;

  // create geometry renderer

  Qt3DRender::QGeometryRenderer *mesh = new Qt3DRender::QGeometryRenderer;
  mesh->setGeometry( new DemTerrainTileGeometry( mResolution, mHeightMap, mesh ) );
  entity->addComponent( mesh ); // takes ownership if the component has no parent

  // create material

  createTextureComponent( entity );

  // create transform

  Qt3DCore::QTransform *transform;
  transform = new Qt3DCore::QTransform();
  entity->addComponent( transform );

  float zMin, zMax;
  _heightMapMinMax( mHeightMap, zMin, zMax );

  const Qgs3DMapSettings &map = terrain()->map3D();
  QgsRectangle extent = map.terrainGenerator()->tilingScheme().tileToExtent( mNode->tileX(), mNode->tileY(), mNode->tileZ() ); //node->extent;
  double x0 = extent.xMinimum() - map.originX();
  double y0 = extent.yMinimum() - map.originY();
  double side = extent.width();
  double half = side / 2;

  transform->setScale3D( QVector3D( side, map.terrainVerticalScale(), side ) );
  transform->setTranslation( QVector3D( x0 + half, 0, - ( y0 + half ) ) );

  mNode->setExactBbox( QgsAABB( x0, zMin * map.terrainVerticalScale(), -y0, x0 + side, zMax * map.terrainVerticalScale(), -( y0 + side ) ) );

  entity->setEnabled( false );
  entity->setParent( parent );
  return entity;
}
    virtual Qt3DCore::QEntity *createEntity( Qt3DCore::QEntity *parent )
    {
      Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;

      // create geometry renderer

      Qt3DRender::QGeometryRenderer *mesh = new Qt3DRender::QGeometryRenderer;
      mesh->setGeometry( new QuantizedMeshGeometry( qmt, mTerrain->map3D(), mapSettings.mapToPixel(), mTerrain->terrainToMapTransform(), mesh ) );
      entity->addComponent( mesh );

      // create material

      createTextureComponent( entity );

      // create transform

      Qt3DCore::QTransform *transform;
      transform = new Qt3DCore::QTransform();
      entity->addComponent( transform );

      const Map3D &map = mTerrain->map3D();

      transform->setScale3D( QVector3D( 1.f, map.zExaggeration, 1.f ) );

      QgsRectangle mapExtent = mapSettings.extent();
      float x0 = mapExtent.xMinimum() - map.originX;
      float y0 = mapExtent.yMinimum() - map.originY;
      float x1 = mapExtent.xMaximum() - map.originX;
      float y1 = mapExtent.yMaximum() - map.originY;
      float z0 = qmt->header.MinimumHeight, z1 = qmt->header.MaximumHeight;

      node->setExactBbox( AABB( x0, z0 * map.zExaggeration, -y0, x1, z1 * map.zExaggeration, -y1 ) );
      //epsilon = mapExtent.width() / map.tileTextureSize;

      entity->setEnabled( false );
      entity->setParent( parent );
      return entity;
    }
Qt3DCore::QEntity *FlatTerrainChunkLoader::createEntity( Qt3DCore::QEntity *parent )
{
  QgsTerrainTileEntity *entity = new QgsTerrainTileEntity;

  // make geometry renderer

  // simple quad geometry shared by all tiles
  // QPlaneGeometry by default is 1x1 with mesh resolution QSize(2,2), centered at 0
  // TODO: the geometry could be shared inside Terrain instance (within terrain-generator specific data?)
  mTileGeometry = new Qt3DExtras::QPlaneGeometry;

  Qt3DRender::QGeometryRenderer *mesh = new Qt3DRender::QGeometryRenderer;
  mesh->setGeometry( mTileGeometry ); // takes ownership if the component has no parent
  entity->addComponent( mesh ); // takes ownership if the component has no parent

  // create material

  createTextureComponent( entity );

  // create transform

  Qt3DCore::QTransform *transform = nullptr;
  transform = new Qt3DCore::QTransform();
  entity->addComponent( transform );

  // set up transform according to the extent covered by the quad geometry
  QgsAABB bbox = mNode->bbox();
  double side = bbox.xMax - bbox.xMin;
  double half = side / 2;

  transform->setScale( side );
  transform->setTranslation( QVector3D( bbox.xMin + half, 0, bbox.zMin + half ) );

  entity->setEnabled( false );
  entity->setParent( parent );
  return entity;
}
Example #6
0
Qt3DRender::QGeometryRenderer *QgsLine3DSymbolEntityNode::rendererSimple( const Qgs3DMapSettings &map, const QgsLine3DSymbol &symbol, const QgsVectorLayer *layer, const QgsFeatureRequest &request )
{
  QVector<QVector3D> vertices;
  vertices << QVector3D();  // the first index is invalid, we use it for primitive restart
  QVector<unsigned int> indexes;

  QgsPoint centroid;
  QgsPointXY origin( map.origin().x(), map.origin().y() );
  QgsFeature f;
  QgsFeatureIterator fi = layer->getFeatures( request );
  while ( fi.nextFeature( f ) )
  {
    if ( f.geometry().isNull() )
      continue;

    if ( symbol.altitudeBinding() == AltBindCentroid )
      centroid = QgsPoint( f.geometry().centroid().asPoint() );

    QgsGeometry geom = f.geometry();
    const QgsAbstractGeometry *g = geom.constGet();
    if ( const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
    {
      for ( int i = 0; i < ls->vertexCount(); ++i )
      {
        QgsPoint p = ls->pointN( i );
        float z = Qgs3DUtils::clampAltitude( p, symbol.altitudeClamping(), symbol.altitudeBinding(), symbol.height(), centroid, map );
        vertices << QVector3D( p.x() - map.origin().x(), z, -( p.y() - map.origin().y() ) );
        indexes << vertices.count() - 1;
      }
    }
    else if ( const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
    {
      for ( int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
      {
        const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( mls->geometryN( nGeom ) );
        for ( int i = 0; i < ls->vertexCount(); ++i )
        {
          QgsPoint p = ls->pointN( i );
          float z = Qgs3DUtils::clampAltitude( p, symbol.altitudeClamping(), symbol.altitudeBinding(), symbol.height(), centroid, map );
          vertices << QVector3D( p.x() - map.origin().x(), z, -( p.y() - map.origin().y() ) );
          indexes << vertices.count() - 1;
        }
        indexes << 0;  // add primitive restart
      }
    }

    indexes << 0;  // add primitive restart
  }

  QByteArray vertexBufferData;
  vertexBufferData.resize( vertices.size() * 3 * sizeof( float ) );
  float *rawVertexArray = reinterpret_cast<float *>( vertexBufferData.data() );
  int idx = 0;
  for ( const auto &v : vertices )
  {
    rawVertexArray[idx++] = v.x();
    rawVertexArray[idx++] = v.y();
    rawVertexArray[idx++] = v.z();
  }

  QByteArray indexBufferData;
  indexBufferData.resize( indexes.size() * sizeof( int ) );
  unsigned int *rawIndexArray = reinterpret_cast<unsigned int *>( indexBufferData.data() );
  idx = 0;
  for ( unsigned int indexVal : indexes )
  {
    rawIndexArray[idx++] = indexVal;
  }

  Qt3DRender::QBuffer *vertexBuffer = new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer, this );
  vertexBuffer->setData( vertexBufferData );

  Qt3DRender::QBuffer *indexBuffer = new Qt3DRender::QBuffer( Qt3DRender::QBuffer::IndexBuffer, this );
  indexBuffer->setData( indexBufferData );

  Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute( this );
  positionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
  positionAttribute->setBuffer( vertexBuffer );
  positionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
  positionAttribute->setVertexSize( 3 );
  positionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );

  Qt3DRender::QAttribute *indexAttribute = new Qt3DRender::QAttribute( this );
  indexAttribute->setAttributeType( Qt3DRender::QAttribute::IndexAttribute );
  indexAttribute->setBuffer( indexBuffer );
  indexAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedInt );

  Qt3DRender::QGeometry *geom = new Qt3DRender::QGeometry;
  geom->addAttribute( positionAttribute );
  geom->addAttribute( indexAttribute );

  Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
  renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStrip );
  renderer->setGeometry( geom );
  renderer->setVertexCount( vertices.count() );
  renderer->setPrimitiveRestartEnabled( true );
  renderer->setRestartIndexValue( 0 );
  return renderer;
}
Example #7
0
Qt3DRender::QGeometryRenderer *QgsPolygon3DSymbolEntityNode::renderer( const Qgs3DMapSettings &map, const QgsPolygon3DSymbol &symbol, const QgsVectorLayer *layer, const QgsFeatureRequest &request )
{
  QgsPointXY origin( map.origin().x(), map.origin().y() );
  QList<QgsPolygon *> polygons;
  QList<float> extrusionHeightPerPolygon;  // will stay empty if not needed per polygon

  QgsExpressionContext ctx( _expressionContext3D() );
  ctx.setFields( layer->fields() );

  const QgsPropertyCollection &ddp = symbol.dataDefinedProperties();
  bool hasDDHeight = ddp.isActive( QgsAbstract3DSymbol::PropertyHeight );
  bool hasDDExtrusion = ddp.isActive( QgsAbstract3DSymbol::PropertyExtrusionHeight );

  QgsFeature f;
  QgsFeatureIterator fi = layer->getFeatures( request );
  while ( fi.nextFeature( f ) )
  {
    if ( f.geometry().isNull() )
      continue;

    QgsGeometry geom = f.geometry();

    // segmentize curved geometries if necessary
    if ( QgsWkbTypes::isCurvedType( geom.constGet()->wkbType() ) )
      geom = QgsGeometry( geom.constGet()->segmentize() );

    const QgsAbstractGeometry *g = geom.constGet();

    ctx.setFeature( f );
    float height = symbol.height();
    float extrusionHeight = symbol.extrusionHeight();
    if ( hasDDHeight )
      height = ddp.valueAsDouble( QgsAbstract3DSymbol::PropertyHeight, ctx, height );
    if ( hasDDExtrusion )
      extrusionHeight = ddp.valueAsDouble( QgsAbstract3DSymbol::PropertyExtrusionHeight, ctx, extrusionHeight );

    if ( const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon *>( g ) )
    {
      QgsPolygon *polyClone = poly->clone();
      Qgs3DUtils::clampAltitudes( polyClone, symbol.altitudeClamping(), symbol.altitudeBinding(), height, map );
      polygons.append( polyClone );
      if ( hasDDExtrusion )
        extrusionHeightPerPolygon.append( extrusionHeight );
    }
    else if ( const QgsMultiPolygon *mpoly = qgsgeometry_cast< const QgsMultiPolygon *>( g ) )
    {
      for ( int i = 0; i < mpoly->numGeometries(); ++i )
      {
        const QgsAbstractGeometry *g2 = mpoly->geometryN( i );
        Q_ASSERT( QgsWkbTypes::flatType( g2->wkbType() ) == QgsWkbTypes::Polygon );
        QgsPolygon *polyClone = static_cast< const QgsPolygon *>( g2 )->clone();
        Qgs3DUtils::clampAltitudes( polyClone, symbol.altitudeClamping(), symbol.altitudeBinding(), height, map );
        polygons.append( polyClone );
        if ( hasDDExtrusion )
          extrusionHeightPerPolygon.append( extrusionHeight );
      }
    }
    else
      qDebug() << "not a polygon";
  }

  mGeometry = new QgsTessellatedPolygonGeometry;
  mGeometry->setPolygons( polygons, origin, symbol.extrusionHeight(), extrusionHeightPerPolygon );

  Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
  renderer->setGeometry( mGeometry );

  return renderer;
}
Example #8
0
void QgsSimpleLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, LineData &out, bool selected )
{
  if ( out.indexes.isEmpty() )
    return;

  // material (only ambient color is used for the color)

  Qt3DExtras::QPhongMaterial *mat = _material( mSymbol );
  if ( selected )
  {
    // update the material with selection colors
    mat->setAmbient( context.map().selectionColor() );
  }

  // geometry renderer

  QByteArray vertexBufferData;
  vertexBufferData.resize( out.vertices.size() * 3 * sizeof( float ) );
  float *rawVertexArray = reinterpret_cast<float *>( vertexBufferData.data() );
  int idx = 0;
  for ( const auto &v : qgis::as_const( out.vertices ) )
  {
    rawVertexArray[idx++] = v.x();
    rawVertexArray[idx++] = v.y();
    rawVertexArray[idx++] = v.z();
  }

  QByteArray indexBufferData;
  indexBufferData.resize( out.indexes.size() * sizeof( int ) );
  unsigned int *rawIndexArray = reinterpret_cast<unsigned int *>( indexBufferData.data() );
  idx = 0;
  for ( unsigned int indexVal : qgis::as_const( out.indexes ) )
  {
    rawIndexArray[idx++] = indexVal;
  }

  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;

  Qt3DRender::QBuffer *vertexBuffer = new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer, entity );
  vertexBuffer->setData( vertexBufferData );

  Qt3DRender::QBuffer *indexBuffer = new Qt3DRender::QBuffer( Qt3DRender::QBuffer::IndexBuffer, entity );
  indexBuffer->setData( indexBufferData );

  Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute( entity );
  positionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
  positionAttribute->setBuffer( vertexBuffer );
  positionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
  positionAttribute->setVertexSize( 3 );
  positionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );

  Qt3DRender::QAttribute *indexAttribute = new Qt3DRender::QAttribute( entity );
  indexAttribute->setAttributeType( Qt3DRender::QAttribute::IndexAttribute );
  indexAttribute->setBuffer( indexBuffer );
  indexAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedInt );

  Qt3DRender::QGeometry *geom = new Qt3DRender::QGeometry;
  geom->addAttribute( positionAttribute );
  geom->addAttribute( indexAttribute );

  Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
  renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStrip );
  renderer->setGeometry( geom );
  renderer->setVertexCount( out.vertices.count() );
  renderer->setPrimitiveRestartEnabled( true );
  renderer->setRestartIndexValue( 0 );

  // make entity
  entity->addComponent( renderer );
  entity->addComponent( mat );
  entity->setParent( parent );
}
    void checkInitialAndCleanedUpState()
    {
        // GIVEN
        Qt3DRender::Render::GeometryRenderer renderGeometryRenderer;

        // THEN
        QVERIFY(renderGeometryRenderer.peerUuid().isNull());
        QVERIFY(renderGeometryRenderer.geometryId().isNull());
        QCOMPARE(renderGeometryRenderer.isDirty(), false);
        QCOMPARE(renderGeometryRenderer.instanceCount(), 0);
        QCOMPARE(renderGeometryRenderer.primitiveCount(), 0);
        QCOMPARE(renderGeometryRenderer.baseVertex(), 0);
        QCOMPARE(renderGeometryRenderer.baseInstance(), 0);
        QCOMPARE(renderGeometryRenderer.restartIndex(), -1);
        QCOMPARE(renderGeometryRenderer.primitiveRestart(), false);
        QCOMPARE(renderGeometryRenderer.primitiveType(), Qt3DRender::QGeometryRenderer::Triangles);
        QVERIFY(renderGeometryRenderer.geometryFunctor().isNull());
        QVERIFY(renderGeometryRenderer.isEnabled());

        // GIVEN
        Qt3DRender::QGeometryRenderer geometryRenderer;
        Qt3DRender::QGeometry geometry;
        Qt3DRender::QGeometryFunctorPtr functor(new TestFunctor(1200));


        geometryRenderer.setInstanceCount(454);
        geometryRenderer.setPrimitiveCount(350);
        geometryRenderer.setBaseVertex(427);
        geometryRenderer.setBaseInstance(383);
        geometryRenderer.setRestartIndex(555);
        geometryRenderer.setPrimitiveRestart(true);
        geometryRenderer.setPrimitiveType(Qt3DRender::QGeometryRenderer::Patches);
        geometryRenderer.setGeometry(&geometry);
        geometryRenderer.setGeometryFunctor(functor);
        geometryRenderer.setEnabled(false);

        // WHEN
        renderGeometryRenderer.updateFromPeer(&geometryRenderer);
        renderGeometryRenderer.cleanup();

        // THEN
        QVERIFY(renderGeometryRenderer.peerUuid().isNull());
        QVERIFY(renderGeometryRenderer.geometryId().isNull());
        QCOMPARE(renderGeometryRenderer.isDirty(), false);
        QCOMPARE(renderGeometryRenderer.instanceCount(), 0);
        QCOMPARE(renderGeometryRenderer.primitiveCount(), 0);
        QCOMPARE(renderGeometryRenderer.baseVertex(), 0);
        QCOMPARE(renderGeometryRenderer.baseInstance(), 0);
        QCOMPARE(renderGeometryRenderer.restartIndex(), -1);
        QCOMPARE(renderGeometryRenderer.primitiveRestart(), false);
        QCOMPARE(renderGeometryRenderer.primitiveType(), Qt3DRender::QGeometryRenderer::Triangles);
        QVERIFY(renderGeometryRenderer.geometryFunctor().isNull());
        QVERIFY(renderGeometryRenderer.isEnabled());
    }