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 ); }
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; }
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; } }