Beispiel #1
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 );
}
Beispiel #2
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;
}
Beispiel #3
0
    void generatedGeometryShouldBeConsistent()
    {
        // GIVEN
        Qt3DExtras::QCuboidGeometry geometry;
        const QVector<Qt3DRender::QAttribute *> attributes = geometry.attributes();
        Qt3DRender::QAttribute *positionAttribute = geometry.positionAttribute();
        Qt3DRender::QAttribute *normalAttribute = geometry.normalAttribute();
        Qt3DRender::QAttribute *texCoordAttribute = geometry.texCoordAttribute();
        Qt3DRender::QAttribute *tangentAttribute = geometry.tangentAttribute();
        Qt3DRender::QAttribute *indexAttribute = geometry.indexAttribute();

        // WHEN
        QFETCH(float, xExtent);
        QFETCH(float, yExtent);
        QFETCH(float, zExtent);
        QFETCH(QSize, xyMeshResolution);
        QFETCH(QSize, yzMeshResolution);
        QFETCH(QSize, xzMeshResolution);
        geometry.setXExtent(xExtent);
        geometry.setYExtent(yExtent);
        geometry.setZExtent(zExtent);
        geometry.setXYMeshResolution(xyMeshResolution);
        geometry.setYZMeshResolution(yzMeshResolution);
        geometry.setXZMeshResolution(xzMeshResolution);

        generateGeometry(geometry);

        // THEN

        // Check buffer of each attribute is valid and actually has some data
        for (const auto &attribute : attributes) {
            Qt3DRender::QBuffer *buffer = attribute->buffer();
            QVERIFY(buffer != nullptr);
            QVERIFY(buffer->data().size() != 0);
        }

        // Check some data in the buffers

        // Check specific indices and vertex attributes of triangle under test
        QFETCH(int, triangleIndex);
        QFETCH(QVector<quint16>, indices);
        QFETCH(QVector<QVector3D>, positions);
        QFETCH(QVector<QVector3D>, normals);
        QFETCH(QVector<QVector2D>, texCoords);
        QFETCH(QVector<QVector4D>, tangents);

        int i = 0;
        for (auto index : indices) {
            const auto testIndex = extractIndexData<quint16>(indexAttribute, 3 * triangleIndex + i);
            QCOMPARE(testIndex, indices.at(i));

            const auto position = extractVertexData<QVector3D, quint32>(positionAttribute, index);
            QCOMPARE(position, positions.at(i));

            const auto normal = extractVertexData<QVector3D, quint32>(normalAttribute, index);
            QCOMPARE(normal, normals.at(i));

            const auto texCoord = extractVertexData<QVector2D, quint32>(texCoordAttribute, index);
            QCOMPARE(texCoord, texCoords.at(i));

            const auto tangent = extractVertexData<QVector4D, quint32>(tangentAttribute, index);
            QCOMPARE(tangent, tangents.at(i));

            ++i;
        }
    }