void PEQGraph::_drawHumpSolid(QSGNode * parentNode, int n, QColor color) {
    //Transparent shaded part//
    QSGGeometryNode * solidNode = new QSGGeometryNode();
    QSGGeometry * solidGeom = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 2 * (HorizontalDivisions + 1));
    QSGFlatColorMaterial *material = new QSGFlatColorMaterial;

    material->setColor(color);
    material->setFlag(QSGMaterial::Blending);

    solidNode->setMaterial(material);
    solidNode->setFlag(QSGNode::OwnsGeometry);
    solidNode->setFlag(QSGNode::OwnedByParent);
    solidNode->setFlag(QSGNode::OwnsMaterial);

    solidGeom->setDrawingMode(GL_TRIANGLE_STRIP);

    QSGGeometry::Point2D* point = solidGeom->vertexDataAsPoint2D();

    float left = graphToNodeX(xAxis.min);
    float mid = graphToNodeY(0);
    float width = graphToNodeX(xAxis.max) - graphToNodeX(xAxis.min);
    float stride = width / HorizontalDivisions;

    for (int i = 0; i < HorizontalDivisions + 1; i++) {
        point->set(left + i*stride, mid);
        point++;
        point->set(left + i*stride, graphToNodeY(computedData[i][n]));
        point++;
    }

    solidNode->setGeometry(solidGeom);
    parentNode->appendChildNode(solidNode);
}
void PEQGraph::_drawHumpOutline(QSGNode * parentNode, int n, QColor color) {
    //Solid Outline
    QSGGeometryNode * lineNode = new QSGGeometryNode();
    QSGGeometry * lineGeom = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), (HorizontalDivisions));

    QSGFlatColorMaterial *material2 = new QSGFlatColorMaterial;

    material2->setColor(color);
    material2->setFlag(QSGMaterial::Blending);

    lineNode->setMaterial(material2);
    lineNode->setFlag(QSGNode::OwnsGeometry);
    lineNode->setFlag(QSGNode::OwnedByParent);
    lineNode->setFlag(QSGNode::OwnsMaterial);

    lineGeom->setDrawingMode(GL_LINE_STRIP);
    glLineWidth(2.0f);

    QSGGeometry::Point2D* point2 = lineGeom->vertexDataAsPoint2D();

    float left = graphToNodeX(xAxis.min);
    float width = graphToNodeX(xAxis.max) - graphToNodeX(xAxis.min);
    float stride = width / HorizontalDivisions;

    for (int i = 0; i < HorizontalDivisions; i++) {
        float x1 = left + (i)*stride;
        float y1 = graphToNodeY(computedData[i][n]);

        point2->set(x1, y1);
        point2++;
    }

    lineNode->setGeometry(lineGeom);
    parentNode->appendChildNode(lineNode);
}
QcLocationCircleNode::QcLocationCircleNode(const QcViewport * viewport)
  : QSGOpacityNode(),
    m_viewport(viewport),
    m_geometry_node(new QSGGeometryNode())
{
  setOpacity(.25); // 1. black

  QSGGeometry * geometry = new QSGGeometry(LocationCirclePoint2D_AttributeSet, 0); // Fixme:
  geometry->setDrawingMode(GL_TRIANGLE_STRIP);
  m_geometry_node->setGeometry(geometry);
  m_geometry_node->setFlag(QSGNode::OwnsGeometry);

  QSGSimpleMaterial<QcLocationCircleMaterialShaderState> * material = QcLocationCircleMaterialShader::createMaterial();
  material->state()->cone_r = 0; // Fixme: QColor
  material->state()->cone_g = 0;
  material->state()->cone_b = 1;
  material->state()->cone_a = 1.;
  material->state()->accuracy_r = 1;
  material->state()->accuracy_g = 0;
  material->state()->accuracy_b = 0;
  material->state()->accuracy_a = 1.;
  // QSGFlatColorMaterial * material = new QSGFlatColorMaterial();
  // material->setColor(QColor("black"));
  material->setFlag(QSGMaterial::Blending);
  m_geometry_node->setMaterial(material);
  m_geometry_node->setFlag(QSGNode::OwnsMaterial);

  appendChildNode(m_geometry_node);
}
QSGNode *PhosphorRender::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
    if (!m_ybuffer) {
        return 0;
    }

    QSGGeometryNode *node = 0;
    QSGGeometry *geometry = 0;
    Material *material = 0;

    unsigned n_points;

    if (m_xbuffer) {
        n_points = std::min(m_xbuffer->size(), m_ybuffer->size());
    } else {
        n_points = m_ybuffer->countPointsBetween(m_xmin, m_xmax);
    }

    n_points = std::min(n_points,(unsigned) 65767);

    if (!oldNode) {
        node = new QSGGeometryNode;
        geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), n_points);
        geometry->setDrawingMode(GL_POINTS);
        node->setGeometry(geometry);
        node->setFlag(QSGNode::OwnsGeometry);
        material = new Material;
        material->setFlag(QSGMaterial::Blending);
        node->setMaterial(material);
        node->setFlag(QSGNode::OwnsMaterial);
    } else {
        node = static_cast<QSGGeometryNode *>(oldNode);
        geometry = node->geometry();
        geometry->allocate(n_points);
        geometry->setLineWidth(m_pointSize);
        material = static_cast<Material*>(node->material());
    }

    QRectF bounds = boundingRect();

    material->transformation.setToIdentity();
    material->transformation.scale(bounds.width()/(m_xmax - m_xmin), bounds.height()/(m_ymin - m_ymax));
    material->transformation.translate(-m_xmin, -m_ymax);

    material->pointSize = m_pointSize;
    material->color = m_color;

    auto verticies = geometry->vertexDataAsPoint2D();
    if (m_xbuffer) {
        for (unsigned i=0; i<n_points; i++) {
            verticies[i].set(m_xbuffer->get(i), m_ybuffer->get(i));
        }
    } else {
        m_ybuffer->toVertexData(m_xmin, m_xmax, verticies, n_points);
    }
    node->markDirty(QSGNode::DirtyGeometry | QSGNode::DirtyMaterial);

    return node;
}
예제 #5
0
/*------------------------------------------------------------------------------
|    OMX_CameraSurfaceElement::updatePaintNode
+-----------------------------------------------------------------------------*/
QSGNode* OMX_CameraSurfaceElement::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*)
{
    QSGGeometryNode* node = 0;
    QSGGeometry* geometry = 0;

    if (!oldNode) {
        // Create the node.
        node = new QSGGeometryNode;
        geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
        geometry->setDrawingMode(GL_TRIANGLE_STRIP);
        node->setGeometry(geometry);
        node->setFlag(QSGNode::OwnsGeometry);

        // TODO: Who is freeing this?
        // TODO: I cannot know the texture size here.
        QSGOpaqueTextureMaterial* material = new QSGOpaqueTextureMaterial;
        m_sgtexture = new OMX_SGTexture(0, QSize(640, 480));
        material->setTexture(m_sgtexture);
        node->setMaterial(material);
        node->setFlag(QSGNode::OwnsMaterial);

        QtConcurrent::run(this, &OMX_CameraSurfaceElement::videoAcquire);
    }
    else {
        node = static_cast<QSGGeometryNode*>(oldNode);
        geometry = node->geometry();
        geometry->allocate(4);

        // Update texture in the node if needed.
        QSGOpaqueTextureMaterial* material = (QSGOpaqueTextureMaterial*)node->material();
        QElapsedTimer timer;
        timer.start();
        QSGTexture* texture = window()->createTextureFromImage(m_frame);
        LOG_VERBOSE(LOG_TAG, "Timer tex: %lld.", timer.elapsed());
        material->setTexture(texture);
        m_semAcquire.release();
#if 0
        if (m_texture != (GLuint)material->texture()->textureId()) {
            // TODO: Does setTextureId frees the prev texture?
            // TODO: I should the given the texture size.
            LOG_ERROR(LOG_TAG, "Updating texture to %u!", m_texture);
            material = new QSGOpaqueTextureMaterial;
            m_sgtexture->setTexture(m_texture, QSize(1920, 1080));
        }
#endif
    }

    // Create the vertices and map to texture.
    QRectF bounds = boundingRect();
    QSGGeometry::TexturedPoint2D* vertices = geometry->vertexDataAsTexturedPoint2D();
    vertices[0].set(bounds.x(), bounds.y() + bounds.height(), 0.0f, 0.0f);
    vertices[1].set(bounds.x() + bounds.width(), bounds.y() + bounds.height(), 1.0f, 0.0f);
    vertices[2].set(bounds.x(), bounds.y(), 0.0f, 1.0f);
    vertices[3].set(bounds.x() + bounds.width(), bounds.y(), 1.0f, 1.0f);
    return node;
}
예제 #6
0
QSGNode * QQuickLineItem::updatePaintNode(QSGNode *prev_node,
                                          UpdatePaintNodeData *upd_data)
{
    Q_UNUSED(upd_data);

    QSGGeometryNode * node = static_cast<QSGGeometryNode*>(prev_node);
    QSGGeometry * geometry = NULL;
    QSGFlatColorMaterial * material = NULL;

    if(!node) {
        // http://qt-project.org/doc/qt-5/qsggeometrynode.html
        node = new QSGGeometryNode;
        geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(),4);
        geometry->setDrawingMode(GL_TRIANGLE_STRIP);
        node->setGeometry(geometry);
        node->setFlag(QSGNode::OwnsGeometry);

        material = new QSGFlatColorMaterial;
        material->setColor(m_color);
        node->setMaterial(material);
        node->setFlag(QSGNode::OwnsMaterial);
    }
    else {
        geometry = node->geometry();
        geometry->allocate(4); // we have to call allocate to invalidate
                               // the older vertex buffer
        material = static_cast<QSGFlatColorMaterial*>(node->material());
    }

    // geometry
    std::vector<QPointF> list_vx;
    if(!calcTriStrip(list_vx)) {
        list_vx.clear();
        list_vx.push_back(QPointF(0,0));
        list_vx.push_back(QPointF(0,0));
        list_vx.push_back(QPointF(0,0));
        list_vx.push_back(QPointF(0,0));
    }

    QSGGeometry::Point2D * vertices =
            geometry->vertexDataAsPoint2D();

    for(size_t i=0; i < list_vx.size(); i++) {
        vertices[i].set(list_vx[i].x(),
                        list_vx[i].y());
    }

    node->markDirty(QSGNode::DirtyGeometry);

    // material
    material->setColor(m_color);
    node->markDirty(QSGNode::DirtyMaterial);

    return node;
}
void SceneGraphDeviceContext::DrawComplexBezierPath(vrv::Point bezier1[4], vrv::Point bezier2[4])
{
    // Note: No support for vertex antialiasing. Use a top-level QQuickView with multisample antialiasing.
    // TODO: Add vertex antialiasing, refer to
    // 1) Qt sources for "void QSGBasicInternalRectangleNode::updateGeometry()" in
    // qtdeclarative/src/quick/scenegraph/qsgbasicinternalrectanglenode.cpp
    // 2) https://stackoverflow.com/questions/28125425/smooth-painting-in-custom-qml-element

    vrv::Pen currentPen = m_penStack.top();

    int segmentCount = 16;

    QSGGeometryNode *node = new QSGGeometryNode;
    QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 2 * segmentCount);
    geometry->setDrawingMode(QSGGeometry::DrawTriangleStrip);
    node->setGeometry(geometry);
    node->setFlag(QSGNode::OwnsGeometry);

    QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
    material->setColor(static_cast<QRgb>(currentPen.GetColour()));
    node->setMaterial(material);
    node->setFlag(QSGNode::OwnsMaterial);

    auto calculateCubicBezierPoint = [](vrv::Point p[4], float t) -> std::tuple<float, float> {
        auto invt = 1 - t;
        auto x = invt * invt * invt * p[0].x + 3 * invt * invt * t * p[1].x + 3 * invt * t * t * p[2].x
            + t * t * t * p[3].x;
        auto y = invt * invt * invt * p[0].y + 3 * invt * invt * t * p[1].y + 3 * invt * t * t * p[2].y
            + t * t * t * p[3].y;
        return std::make_tuple(x, y);
    };

    // This loop calculates the bezier points for the inner and the outer line and add them as vertices. The list of
    // vertices is built so that points from the inner and outer line are alternating. This allows to draw a filled area
    // with DrawTriangleStrip.
    QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D();
    for (int i = 0; i < segmentCount; ++i) {
        float bezierPointX = 0;
        float bezierPointY = 0;
        float currentSegment = i / static_cast<float>(segmentCount - 1);

        // Calculate bezier point on bezier1
        std::tie(bezierPointX, bezierPointY) = calculateCubicBezierPoint(bezier1, currentSegment);
        vertices[i * 2].set(translateX(bezierPointX), translateY(bezierPointY));

        // Calculate bezier point on bezier2
        std::tie(bezierPointX, bezierPointY) = calculateCubicBezierPoint(bezier2, currentSegment);
        vertices[i * 2 + 1].set(translateX(bezierPointX), translateY(bezierPointY));
    }

    node->markDirty(QSGNode::DirtyGeometry);
    AddGeometryNode(node);
}
예제 #8
0
//! [4]
QSGNode *BezierCurve::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
    QSGGeometryNode *node = 0;
    QSGGeometry *geometry = 0;

    if (!oldNode) {
        node = new QSGGeometryNode;
//! [4] //! [5]
        geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), m_segmentCount);
        geometry->setLineWidth(2);
        geometry->setDrawingMode(GL_LINE_STRIP);
        node->setGeometry(geometry);
        node->setFlag(QSGNode::OwnsGeometry);
//! [5] //! [6]
        QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
        material->setColor(QColor(255, 0, 0));
        node->setMaterial(material);
        node->setFlag(QSGNode::OwnsMaterial);
//! [6] //! [7]
    } else {
        node = static_cast<QSGGeometryNode *>(oldNode);
        geometry = node->geometry();
        geometry->allocate(m_segmentCount);
    }
//! [7]

//! [8]
    QRectF bounds = boundingRect();
    QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D();
    for (int i = 0; i < m_segmentCount; ++i) {
        qreal t = i / qreal(m_segmentCount - 1);
        qreal invt = 1 - t;

        QPointF pos = invt * invt * invt * m_p1
                    + 3 * invt * invt * t * m_p2
                    + 3 * invt * t * t * m_p3
                    + t * t * t * m_p4;

        float x = bounds.x() + pos.x() * bounds.width();
        float y = bounds.y() + pos.y() * bounds.height();

        vertices[i].set(x, y);
    }
    node->markDirty(QSGNode::DirtyGeometry);
//! [8]


//! [9]
    return node;
}
void DynamicController::drawGateCompressor(QSGNode * rootNode) {

    if (knobs.count() == 0) {
        return;
    }
    //Update knobs
    if (!this->simple()) {
        QObject * gateKnob = knobs[0];
        QObject * compThreshKnob = knobs[1];
        QObject * compRatioKnob = knobs[2];

        gateKnob->setProperty("x", graphToNodeX(_tempModel["gatex"]));
        gateKnob->setProperty("y", graphToNodeY(_tempModel["gatey"]));

        compThreshKnob->setProperty("x", graphToNodeX(_tempModel["compx"]));
        compThreshKnob->setProperty("y", graphToNodeY(_tempModel["compy"]));

        compRatioKnob->setProperty("x", graphToNodeX(xAxis.max));
        compRatioKnob->setProperty("y", graphToNodeY(_tempModel["compy"]) * (1 - _tempModel["ratio"]));
    }

    QSGGeometryNode * lineNode = new QSGGeometryNode();
    QSGGeometry * lineGeom = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), (4));

    QSGFlatColorMaterial *material = new QSGFlatColorMaterial;

    material->setColor(this->curveColor());
    material->setFlag(QSGMaterial::Blending);

    lineNode->setMaterial(material);
    lineNode->setFlag(QSGNode::OwnsGeometry);
    lineNode->setFlag(QSGNode::OwnedByParent);
    lineNode->setFlag(QSGNode::OwnsMaterial);

    lineGeom->setDrawingMode(GL_LINE_STRIP);
    glLineWidth(2.0f);

    QSGGeometry::Point2D* points = lineGeom->vertexDataAsPoint2D();

    QRectF bounds = boundingRect();

    points->set(graphToNodeX(_tempModel["gatex"]), bounds.bottom()); points++;
    points->set(graphToNodeX(_tempModel["gatex"]), graphToNodeY(_tempModel["gatey"])); points++;
    points->set(graphToNodeX(_tempModel["compx"]), graphToNodeY(_tempModel["compy"])); points++;
    points->set(graphToNodeX(xAxis.max), graphToNodeY(_tempModel["compy"]) * (1 - _tempModel["ratio"])); points++;

    lineNode->setGeometry(lineGeom);
    rootNode->appendChildNode(lineNode);
}
QSGGeometryNode *createSelectionNode(QSGMaterial *material)
{
    QSGGeometryNode *selectionNode = new QSGGeometryNode;
    selectionNode->setMaterial(material);
    selectionNode->setFlag(QSGNode::OwnsMaterial, false);
    QSGGeometry *geometry = new QSGGeometry(OpaqueColoredPoint2DWithSize::attributes(), 4);
    geometry->setDrawingMode(GL_TRIANGLE_STRIP);
    OpaqueColoredPoint2DWithSize *v = OpaqueColoredPoint2DWithSize::fromVertexData(geometry);
    for (int i = 0; i < 4; ++i)
        v[i].set(0, 0, 0, 0, 0, 0, 0, 0);
    selectionNode->setGeometry(geometry);
    selectionNode->setFlag(QSGNode::OwnsGeometry, true);
    selectionNode->setFlag(QSGNode::OwnedByParent, false);
    return selectionNode;
}
void SceneGraphDeviceContext::DrawPolygon(int n, vrv::Point points[], int xoffset, int yoffset, int)
{
    // Note: No support for vertex antialiasing. Use a top-level QQuickView with multisample antialiasing.
    // TODO: Add vertex antialiasing, refer to
    // 1) Qt sources for "void QSGBasicInternalRectangleNode::updateGeometry()" in
    // qtdeclarative/src/quick/scenegraph/qsgbasicinternalrectanglenode.cpp
    // 2) https://stackoverflow.com/questions/28125425/smooth-painting-in-custom-qml-element

    // TODO: This function only works for convex polygons. At the moment verovio calls this function only with n = 4.
    // Maybe this function should be renamed to DrawConvexPolygon

    vrv::Pen currentPen = m_penStack.top();

    QSGGeometry *geometry;
    geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), n);
    geometry->setDrawingMode(QSGGeometry::DrawTriangleStrip);

    QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
    material->setColor(static_cast<QRgb>(currentPen.GetColour()));

    // Reorder points so that they can be drawn with DrawTriangleStrip.
    int counter1 = 0;
    int counter2 = n - 1;
    for (int i = 0; i < n; i++) {
        if (i % 2 == 0) {
            geometry->vertexDataAsPoint2D()[i].set(
                translateX(points[counter1].x + xoffset), translateY(points[counter1].y + yoffset));
            counter1++;
        }
        else {
            geometry->vertexDataAsPoint2D()[i].set(
                translateX(points[counter2].x + xoffset), translateY(points[counter2].y + yoffset));
            counter2--;
        }
    }

    QSGGeometryNode *node = new QSGGeometryNode;
    node->setGeometry(geometry);
    node->setFlag(QSGNode::OwnsGeometry);
    node->setMaterial(material);
    node->setFlag(QSGNode::OwnsMaterial);

    AddGeometryNode(node);
}
void DynamicController::drawCompressor(QSGNode * rootNode) {
    //Update knobs
    if (!this->simple()) {
        QObject * threshKnob = knobs[0];
        QObject * ratKnob = knobs[1];

        threshKnob->setProperty("x", graphToNodeX(_tempModel["compx"]));
        threshKnob->setProperty("y", graphToNodeY(_tempModel["compy"]));

        ratKnob->setProperty("x", graphToNodeX(yAxis.max));
        ratKnob->setProperty("y", graphToNodeY(_tempModel["compy"]) * (1 - _tempModel["ratio"]));
    }

    QSGGeometryNode * lineNode = new QSGGeometryNode();
    QSGGeometry * lineGeom = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), (3));

    QSGFlatColorMaterial *material = new QSGFlatColorMaterial;

    material->setColor(this->curveColor());
    material->setFlag(QSGMaterial::Blending);

    lineNode->setMaterial(material);
    lineNode->setFlag(QSGNode::OwnsGeometry);
    lineNode->setFlag(QSGNode::OwnedByParent);
    lineNode->setFlag(QSGNode::OwnsMaterial);

    lineGeom->setDrawingMode(GL_LINE_STRIP);
    glLineWidth(2.0f);

    QSGGeometry::Point2D* points = lineGeom->vertexDataAsPoint2D();

    QRectF bounds = boundingRect();

    points->set(bounds.left(), bounds.bottom()); points++;

    for (int i = 0; i < 2; i++) {
        QQuickItem * q = qobject_cast<QQuickItem*>(knobs[i]);
        points->set(q->x(), q->y());
        points++;
    }

    lineNode->setGeometry(lineGeom);
    rootNode->appendChildNode(lineNode);
}
void SceneGraphDeviceContext::DrawLine(int x1, int y1, int x2, int y2)
{
    vrv::Pen currentPen = m_penStack.top();

    QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 2);
    geometry->setDrawingMode(GL_LINES);
    geometry->setLineWidth(translate(currentPen.GetWidth()));
    geometry->vertexDataAsPoint2D()[0].set(translateX(x1), translateY(y1));
    geometry->vertexDataAsPoint2D()[1].set(translateX(x2), translateY(y2));

    QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
    material->setColor(static_cast<QRgb>(currentPen.GetColour()));

    QSGGeometryNode *node = new QSGGeometryNode;
    node->setGeometry(geometry);
    node->setFlag(QSGNode::OwnsGeometry);
    node->setMaterial(material);
    node->setFlag(QSGNode::OwnsMaterial);

    AddGeometryNode(node);
}
예제 #14
0
QSGNode* drawRect(const QRect& rect, QSGNode* oldNode)
{
    QSGGeometryNode* node;
    if (oldNode == nullptr)
    {
        node = new QSGGeometryNode;

        QSGGeometry* geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 8);
        geometry->setDrawingMode(GL_LINES);
        geometry->setLineWidth(1);

        QSGFlatColorMaterial* material = new QSGFlatColorMaterial;
        material->setColor(QGuiApplication::palette().color(QPalette::Normal, QPalette::WindowText));

        node->setGeometry(geometry);
        node->setFlag(QSGNode::OwnsGeometry);
        node->setMaterial(material);
        node->setFlag(QSGNode::OwnsMaterial);
    }
    else
    {
        node = static_cast<QSGGeometryNode*>(oldNode);
    }

    QSGGeometry* geometry = node->geometry();

    // FIXME: check if these really have to be updated
    geometry->vertexDataAsPoint2D()[0].set(rect.topLeft().x(), rect.topLeft().y());
    geometry->vertexDataAsPoint2D()[1].set(rect.topRight().x(), rect.topRight().y());
    geometry->vertexDataAsPoint2D()[2].set(rect.topRight().x(), rect.topRight().y());
    geometry->vertexDataAsPoint2D()[3].set(rect.bottomRight().x(), rect.bottomRight().y());
    geometry->vertexDataAsPoint2D()[4].set(rect.bottomRight().x(), rect.bottomRight().y());
    geometry->vertexDataAsPoint2D()[5].set(rect.bottomLeft().x(), rect.bottomLeft().y());
    geometry->vertexDataAsPoint2D()[6].set(rect.bottomLeft().x(), rect.bottomLeft().y());
    geometry->vertexDataAsPoint2D()[7].set(rect.topLeft().x(), rect.topLeft().y());

    node->markDirty(QSGNode::DirtyGeometry);

    return node;
}
예제 #15
0
QSGNode *QPScrollingCurve::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
{
    QSGGeometryNode *node = 0;
    QSGGeometry *geometry = 0;
    QSGFlatColorMaterial *material = 0;

    if (!oldNode) {
        node = new QSGGeometryNode;
        geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), m_data.size());
        geometry->setLineWidth(2);
        geometry->setDrawingMode(GL_LINE_STRIP);
        node->setGeometry(geometry);
        node->setFlag(QSGNode::OwnsGeometry);
        material = new QSGFlatColorMaterial;
        material->setColor(m_color);
        node->setMaterial(material);
        node->setFlag(QSGNode::OwnsMaterial);
        node->markDirty(QSGNode::DirtyMaterial);
    } else {
        node = static_cast<QSGGeometryNode *>(oldNode);
        geometry = node->geometry();
        geometry->allocate(m_data.size());
        material = static_cast<QSGFlatColorMaterial*>(node->material());
        if (material->color() != m_color) {
            material->setColor(m_color);
            node->markDirty(QSGNode::DirtyMaterial);
        }
    }

    QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D();

    for (uint i = 0; i < m_data.size(); ++i) {
        QPointF p(i, m_data[i]);
        vertices[i].set(p.x(), p.y());
    }

    node->markDirty(QSGNode::DirtyGeometry);

    return node;
}
예제 #16
0
QSGGeometry *NotesGeometry::createGeometry(QVector<int> &ids, const TimelineModel *model,
                                           const TimelineRenderState *parentState, bool collapsed)
{
    float rowHeight = TimelineModel::defaultRowHeight();
    QSGGeometry *geometry = new QSGGeometry(point2DWithDistanceFromTop(),
                                            ids.count() * 2);
    geometry->setDrawingMode(GL_LINES);
    geometry->setLineWidth(3);
    Point2DWithDistanceFromTop *v =
            static_cast<Point2DWithDistanceFromTop *>(geometry->vertexData());
    for (int i = 0; i < ids.count(); ++i) {
        int timelineIndex = ids[i];
        float horizontalCenter = ((model->startTime(timelineIndex) +
                                   model->endTime(timelineIndex)) / (qint64)2 -
                                  parentState->start()) * parentState->scale();
        float verticalStart = (collapsed ? (model->collapsedRow(timelineIndex) + 0.1) : 0.1) *
                rowHeight;
        float verticalEnd = verticalStart + 0.8 * rowHeight;
        v[i * 2].set(horizontalCenter, verticalStart, 0);
        v[i * 2 + 1].set(horizontalCenter, verticalEnd, 1);
    }
    return geometry;
}
void SceneGraphDeviceContext::DrawCircle(int x, int y, int radius)
{
    // Note: No support for vertex antialiasing. Use a top-level QQuickView with multisample antialiasing.
    // TODO: Add vertex antialiasing, refer to
    // 1) Qt sources for "void QSGBasicInternalRectangleNode::updateGeometry()" in
    // qtdeclarative/src/quick/scenegraph/qsgbasicinternalrectanglenode.cpp
    // 2) https://stackoverflow.com/questions/28125425/smooth-painting-in-custom-qml-element

    vrv::Pen currentPen = m_penStack.top();

    int segmentCount = 16;

    QSGGeometryNode *node = new QSGGeometryNode();
    QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), segmentCount);
    geometry->setDrawingMode(QSGGeometry::DrawTriangleFan);
    node->setGeometry(geometry);
    node->setFlag(QSGNode::OwnsGeometry);

    QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
    material->setColor(static_cast<QRgb>(currentPen.GetColour()));
    node->setMaterial(material);
    node->setFlag(QSGNode::OwnsMaterial);

    // This draws individual triangles from the first point (center) to every outer point by using DrawTriangleFan.
    QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D();
    int numPoints = geometry->vertexCount();
    vertices[0].x = translateX(x);
    vertices[0].y = translateY(y);
    for (int i = 1; i < numPoints; ++i) {
        double theta = i * 2 * M_PI / (numPoints - 2);
        vertices[i].x = translateX(x + radius * static_cast<float>(std::cos(theta)));
        vertices[i].y = translateY(y - radius * static_cast<float>(std::sin(theta)));
    }

    node->markDirty(QSGNode::DirtyGeometry);
    AddGeometryNode(node);
}
void QQuickShapeGenericRenderer::updateStrokeNode(ShapePathData *d, QQuickShapeGenericNode *node)
{
    if (!node->m_strokeNode)
        return;
    if (!(d->effectiveDirty & (DirtyStrokeGeom | DirtyColor)))
        return;

    QQuickShapeGenericStrokeFillNode *n = node->m_strokeNode;
    QSGGeometry *g = n->geometry();
    if (d->strokeVertices.isEmpty()) {
        if (g->vertexCount() || g->indexCount()) {
            g->allocate(0, 0);
            n->markDirty(QSGNode::DirtyGeometry);
        }
        return;
    }

    n->markDirty(QSGNode::DirtyGeometry);

    // Async loading runs update once, bails out above, then updates again once
    // ready. Set the material dirty then. This is in-line with fill where the
    // first activateMaterial() achieves the same.
    if (!g->vertexCount())
        n->markDirty(QSGNode::DirtyMaterial);

    if ((d->effectiveDirty & DirtyColor) && !(d->effectiveDirty & DirtyStrokeGeom)) {
        ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(g->vertexData());
        for (int i = 0; i < g->vertexCount(); ++i)
            vdst[i].set(vdst[i].x, vdst[i].y, d->strokeColor);
        return;
    }

    g->allocate(d->strokeVertices.count(), 0);
    g->setDrawingMode(QSGGeometry::DrawTriangleStrip);
    memcpy(g->vertexData(), d->strokeVertices.constData(), g->vertexCount() * g->sizeOfVertex());
}
void DynamicController::drawGate(QSGNode * rootNode) {
    //Update knobs
    if (!this->simple()) {
        QObject * gateKnob = knobs[0];

        gateKnob->setProperty("x", graphToNodeX(_tempModel["gatex"]));
        gateKnob->setProperty("y", graphToNodeY(_tempModel["gatey"]));
    }

    QSGGeometryNode * lineNode = new QSGGeometryNode();
    QSGGeometry * lineGeom = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), (3));

    QSGFlatColorMaterial *material = new QSGFlatColorMaterial;

    material->setColor(this->curveColor());
    material->setFlag(QSGMaterial::Blending);

    lineNode->setMaterial(material);
    lineNode->setFlag(QSGNode::OwnsGeometry);
    lineNode->setFlag(QSGNode::OwnedByParent);
    lineNode->setFlag(QSGNode::OwnsMaterial);

    lineGeom->setDrawingMode(GL_LINE_STRIP);
    glLineWidth(2.0f);

    QSGGeometry::Point2D* points = lineGeom->vertexDataAsPoint2D();

    QRectF bounds = boundingRect();

    points->set(graphToNodeX(_tempModel["gatex"]), bounds.bottom()); points++;
    points->set(graphToNodeX(_tempModel["gatex"]), graphToNodeX(_tempModel["gatey"])); points++;
    points->set(bounds.right(), bounds.top()); points++;

    lineNode->setGeometry(lineGeom);
    rootNode->appendChildNode(lineNode);
}
void
QcLocationCircleNode::update(const QcLocationCircleData & location_circle_data)
{
  // QSGGeometry * location_circle_geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 1);
  // location_circle_geometry->setLineWidth(100); // point size, max is 255
  // location_circle_geometry->setDrawingMode(GL_POINTS);

  QSGGeometry * geometry = new QSGGeometry(LocationCirclePoint2D_AttributeSet, 4);
  geometry->setDrawingMode(GL_TRIANGLE_STRIP);
  m_geometry_node->setGeometry(geometry);
  m_geometry_node->setFlag(QSGNode::OwnsGeometry);

  LocationCirclePoint2D * vertices = static_cast<LocationCirclePoint2D *>(geometry->vertexData());
  float x, y;
  if (location_circle_data.visible()) {
    QcVectorDouble screen_coordinate = m_viewport->coordinate_to_screen(location_circle_data.coordinate());
    x = screen_coordinate.x();
    y = screen_coordinate.y();
    qInfo() << screen_coordinate;
  } else {
    x = .5 * m_viewport->width(); // Fixme: vector
    y = .5 * m_viewport->height();
  }
  float accuracy_radius = m_viewport->to_px(location_circle_data.horizontal_precision());
  constexpr float dot_radius_minimum = 10.;
  constexpr float cone_scale_factor = 5.;
  float dot_radius = qMax(accuracy_radius, dot_radius_minimum);
  float radius = cone_scale_factor * dot_radius_minimum;
  float margin = 10;
  float size = radius + margin;
  float angle = location_circle_data.bearing() + 90.; // North point to y
  vertices[0].set(QcVectorDouble(x - size, y - size), QcVectorDouble(-size, -size), radius, dot_radius, accuracy_radius, angle);
  vertices[1].set(QcVectorDouble(x - size, y + size), QcVectorDouble(-size,  size), radius, dot_radius, accuracy_radius, angle);
  vertices[2].set(QcVectorDouble(x + size, y - size), QcVectorDouble( size, -size), radius, dot_radius, accuracy_radius, angle);
  vertices[3].set(QcVectorDouble(x + size, y + size), QcVectorDouble( size,  size), radius, dot_radius, accuracy_radius, angle);
}
void QSGDefaultImageNode::updateGeometry()
{
    Q_ASSERT(!m_targetRect.isEmpty());
    const QSGTexture *t = m_material.texture();
    if (!t) {
        QSGGeometry *g = geometry();
        g->allocate(4);
        g->setDrawingMode(GL_TRIANGLE_STRIP);
        memset(g->vertexData(), 0, g->sizeOfVertex() * 4);
    } else {
        QRectF sourceRect = t->normalizedTextureSubRect();

        QRectF innerSourceRect(sourceRect.x() + m_innerSourceRect.x() * sourceRect.width(),
                               sourceRect.y() + m_innerSourceRect.y() * sourceRect.height(),
                               m_innerSourceRect.width() * sourceRect.width(),
                               m_innerSourceRect.height() * sourceRect.height());

        bool hasMargins = m_targetRect != m_innerTargetRect;

        int floorLeft = qFloor(m_subSourceRect.left());
        int ceilRight = qCeil(m_subSourceRect.right());
        int floorTop = qFloor(m_subSourceRect.top());
        int ceilBottom = qCeil(m_subSourceRect.bottom());
        int hTiles = ceilRight - floorLeft;
        int vTiles = ceilBottom - floorTop;

        bool hasTiles = hTiles != 1 || vTiles != 1;
        bool fullTexture = innerSourceRect == QRectF(0, 0, 1, 1);

#ifdef QT_OPENGL_ES_2
        QOpenGLContext *ctx = QOpenGLContext::currentContext();
        bool npotSupported = ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat);
        QSize size = t->textureSize();
        bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
        bool wrapSupported = npotSupported || !isNpot;
#else
        bool wrapSupported = true;
#endif

        // An image can be rendered as a single quad if:
        // - There are no margins, and either:
        //   - the image isn't repeated
        //   - the source rectangle fills the entire texture so that texture wrapping can be used,
        //     and NPOT is supported
        if (!hasMargins && (!hasTiles || (fullTexture && wrapSupported))) {
            QRectF sr;
            if (!fullTexture) {
                sr = QRectF(innerSourceRect.x() + (m_subSourceRect.left() - floorLeft) * innerSourceRect.width(),
                            innerSourceRect.y() + (m_subSourceRect.top() - floorTop) * innerSourceRect.height(),
                            m_subSourceRect.width() * innerSourceRect.width(),
                            m_subSourceRect.height() * innerSourceRect.height());
            } else {
                sr = QRectF(m_subSourceRect.left() - floorLeft, m_subSourceRect.top() - floorTop,
                            m_subSourceRect.width(), m_subSourceRect.height());
            }
            if (m_mirror) {
                qreal oldLeft = sr.left();
                sr.setLeft(sr.right());
                sr.setRight(oldLeft);
            }

            if (m_antialiasing) {
                QSGGeometry *g = geometry();
                Q_ASSERT(g != &m_geometry);
                g->allocate(8, 14);
                g->setDrawingMode(GL_TRIANGLE_STRIP);
                SmoothVertex *vertices = reinterpret_cast<SmoothVertex *>(g->vertexData());
                float delta = float(qAbs(m_targetRect.width()) < qAbs(m_targetRect.height())
                        ? m_targetRect.width() : m_targetRect.height()) * 0.5f;
                float sx = float(sr.width() / m_targetRect.width());
                float sy = float(sr.height() / m_targetRect.height());
                for (int d = -1; d <= 1; d += 2) {
                    for (int j = 0; j < 2; ++j) {
                        for (int i = 0; i < 2; ++i, ++vertices) {
                            vertices->x = m_targetRect.x() + i * m_targetRect.width();
                            vertices->y = m_targetRect.y() + j * m_targetRect.height();
                            vertices->u = sr.x() + i * sr.width();
                            vertices->v = sr.y() + j * sr.height();
                            vertices->dx = (i == 0 ? delta : -delta) * d;
                            vertices->dy = (j == 0 ? delta : -delta) * d;
                            vertices->du = (d < 0 ? 0 : vertices->dx * sx);
                            vertices->dv = (d < 0 ? 0 : vertices->dy * sy);
                        }
                    }
                }
                Q_ASSERT(vertices - g->vertexCount() == g->vertexData());
                static const quint16 indices[] = {
                    0, 4, 1, 5, 3, 7, 2, 6, 0, 4,
                    4, 6, 5, 7
                };
                Q_ASSERT(g->sizeOfIndex() * g->indexCount() == sizeof(indices));
                memcpy(g->indexDataAsUShort(), indices, sizeof(indices));
            } else {
                m_geometry.allocate(4);
                m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
                QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_targetRect, sr);
            }
        } else {
            int hCells = hTiles;
            int vCells = vTiles;
            if (m_innerTargetRect.width() == 0)
                hCells = 0;
            if (m_innerTargetRect.left() != m_targetRect.left())
                ++hCells;
            if (m_innerTargetRect.right() != m_targetRect.right())
                ++hCells;
            if (m_innerTargetRect.height() == 0)
                vCells = 0;
            if (m_innerTargetRect.top() != m_targetRect.top())
                ++vCells;
            if (m_innerTargetRect.bottom() != m_targetRect.bottom())
                ++vCells;
            QVarLengthArray<X, 32> xData(2 * hCells);
            QVarLengthArray<Y, 32> yData(2 * vCells);
            X *xs = xData.data();
            Y *ys = yData.data();

            if (m_innerTargetRect.left() != m_targetRect.left()) {
                xs[0].x = m_targetRect.left();
                xs[0].tx = sourceRect.left();
                xs[1].x = m_innerTargetRect.left();
                xs[1].tx = innerSourceRect.left();
                xs += 2;
            }
            if (m_innerTargetRect.width() != 0) {
                xs[0].x = m_innerTargetRect.left();
                xs[0].tx = innerSourceRect.x() + (m_subSourceRect.left() - floorLeft) * innerSourceRect.width();
                ++xs;
                float b = m_innerTargetRect.width() / m_subSourceRect.width();
                float a = m_innerTargetRect.x() - m_subSourceRect.x() * b;
                for (int i = floorLeft + 1; i <= ceilRight - 1; ++i) {
                    xs[0].x = xs[1].x = a + b * i;
                    xs[0].tx = innerSourceRect.right();
                    xs[1].tx = innerSourceRect.left();
                    xs += 2;
                }
                xs[0].x = m_innerTargetRect.right();
                xs[0].tx = innerSourceRect.x() + (m_subSourceRect.right() - ceilRight + 1) * innerSourceRect.width();
                ++xs;
            }
            if (m_innerTargetRect.right() != m_targetRect.right()) {
                xs[0].x = m_innerTargetRect.right();
                xs[0].tx = innerSourceRect.right();
                xs[1].x = m_targetRect.right();
                xs[1].tx = sourceRect.right();
                xs += 2;
            }
            Q_ASSERT(xs == xData.data() + xData.size());
            if (m_mirror) {
                float leftPlusRight = m_targetRect.left() + m_targetRect.right();
                int count = xData.size();
                xs = xData.data();
                for (int i = 0; i < count >> 1; ++i)
                    qSwap(xs[i], xs[count - 1 - i]);
                for (int i = 0; i < count; ++i)
                    xs[i].x = leftPlusRight - xs[i].x;
            }

            if (m_innerTargetRect.top() != m_targetRect.top()) {
                ys[0].y = m_targetRect.top();
                ys[0].ty = sourceRect.top();
                ys[1].y = m_innerTargetRect.top();
                ys[1].ty = innerSourceRect.top();
                ys += 2;
            }
            if (m_innerTargetRect.height() != 0) {
                ys[0].y = m_innerTargetRect.top();
                ys[0].ty = innerSourceRect.y() + (m_subSourceRect.top() - floorTop) * innerSourceRect.height();
                ++ys;
                float b = m_innerTargetRect.height() / m_subSourceRect.height();
                float a = m_innerTargetRect.y() - m_subSourceRect.y() * b;
                for (int i = floorTop + 1; i <= ceilBottom - 1; ++i) {
                    ys[0].y = ys[1].y = a + b * i;
                    ys[0].ty = innerSourceRect.bottom();
                    ys[1].ty = innerSourceRect.top();
                    ys += 2;
                }
                ys[0].y = m_innerTargetRect.bottom();
                ys[0].ty = innerSourceRect.y() + (m_subSourceRect.bottom() - ceilBottom + 1) * innerSourceRect.height();
                ++ys;
            }
            if (m_innerTargetRect.bottom() != m_targetRect.bottom()) {
                ys[0].y = m_innerTargetRect.bottom();
                ys[0].ty = innerSourceRect.bottom();
                ys[1].y = m_targetRect.bottom();
                ys[1].ty = sourceRect.bottom();
                ys += 2;
            }
            Q_ASSERT(ys == yData.data() + yData.size());

            if (m_antialiasing) {
                QSGGeometry *g = geometry();
                Q_ASSERT(g != &m_geometry);

                g->allocate(hCells * vCells * 4 + (hCells + vCells - 1) * 4,
                            hCells * vCells * 6 + (hCells + vCells) * 12);
                g->setDrawingMode(GL_TRIANGLES);
                SmoothVertex *vertices = reinterpret_cast<SmoothVertex *>(g->vertexData());
                memset(vertices, 0, g->vertexCount() * g->sizeOfVertex());
                quint16 *indices = g->indexDataAsUShort();

                // The deltas are how much the fuzziness can reach into the image.
                // Only the border vertices are moved by the vertex shader, so the fuzziness
                // can't reach further into the image than the closest interior vertices.
                float leftDx = xData.at(1).x - xData.at(0).x;
                float rightDx = xData.at(xData.size() - 1).x - xData.at(xData.size() - 2).x;
                float topDy = yData.at(1).y - yData.at(0).y;
                float bottomDy = yData.at(yData.size() - 1).y - yData.at(yData.size() - 2).y;

                float leftDu = xData.at(1).tx - xData.at(0).tx;
                float rightDu = xData.at(xData.size() - 1).tx - xData.at(xData.size() - 2).tx;
                float topDv = yData.at(1).ty - yData.at(0).ty;
                float bottomDv = yData.at(yData.size() - 1).ty - yData.at(yData.size() - 2).ty;

                if (hCells == 1) {
                    leftDx = rightDx *= 0.5f;
                    leftDu = rightDu *= 0.5f;
                }
                if (vCells == 1) {
                    topDy = bottomDy *= 0.5f;
                    topDv = bottomDv *= 0.5f;
                }

                // This delta is how much the fuzziness can reach out from the image.
                float delta = float(qAbs(m_targetRect.width()) < qAbs(m_targetRect.height())
                                    ? m_targetRect.width() : m_targetRect.height()) * 0.5f;

                quint16 index = 0;
                ys = yData.data();
                for (int j = 0; j < vCells; ++j, ys += 2) {
                    xs = xData.data();
                    bool isTop = j == 0;
                    bool isBottom = j == vCells - 1;
                    for (int i = 0; i < hCells; ++i, xs += 2) {
                        bool isLeft = i == 0;
                        bool isRight = i == hCells - 1;

                        SmoothVertex *v = vertices + index;

                        quint16 topLeft = index;
                        for (int k = (isTop || isLeft ? 2 : 1); k--; ++v, ++index) {
                            v->x = xs[0].x;
                            v->u = xs[0].tx;
                            v->y = ys[0].y;
                            v->v = ys[0].ty;
                        }

                        quint16 topRight = index;
                        for (int k = (isTop || isRight ? 2 : 1); k--; ++v, ++index) {
                            v->x = xs[1].x;
                            v->u = xs[1].tx;
                            v->y = ys[0].y;
                            v->v = ys[0].ty;
                        }

                        quint16 bottomLeft = index;
                        for (int k = (isBottom || isLeft ? 2 : 1); k--; ++v, ++index) {
                            v->x = xs[0].x;
                            v->u = xs[0].tx;
                            v->y = ys[1].y;
                            v->v = ys[1].ty;
                        }

                        quint16 bottomRight = index;
                        for (int k = (isBottom || isRight ? 2 : 1); k--; ++v, ++index) {
                            v->x = xs[1].x;
                            v->u = xs[1].tx;
                            v->y = ys[1].y;
                            v->v = ys[1].ty;
                        }

                        appendQuad(&indices, topLeft, topRight, bottomLeft, bottomRight);

                        if (isTop) {
                            vertices[topLeft].dy = vertices[topRight].dy = topDy;
                            vertices[topLeft].dv = vertices[topRight].dv = topDv;
                            vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -delta;
                            appendQuad(&indices, topLeft + 1, topRight + 1, topLeft, topRight);
                        }

                        if (isBottom) {
                            vertices[bottomLeft].dy = vertices[bottomRight].dy = -bottomDy;
                            vertices[bottomLeft].dv = vertices[bottomRight].dv = -bottomDv;
                            vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = delta;
                            appendQuad(&indices, bottomLeft, bottomRight, bottomLeft + 1, bottomRight + 1);
                        }

                        if (isLeft) {
                            vertices[topLeft].dx = vertices[bottomLeft].dx = leftDx;
                            vertices[topLeft].du = vertices[bottomLeft].du = leftDu;
                            vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -delta;
                            appendQuad(&indices, topLeft + 1, topLeft, bottomLeft + 1, bottomLeft);
                        }

                        if (isRight) {
                            vertices[topRight].dx = vertices[bottomRight].dx = -rightDx;
                            vertices[topRight].du = vertices[bottomRight].du = -rightDu;
                            vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = delta;
                            appendQuad(&indices, topRight, topRight + 1, bottomRight, bottomRight + 1);
                        }
                    }
                }

                Q_ASSERT(index == g->vertexCount());
                Q_ASSERT(indices - g->indexCount() == g->indexData());
            } else {
                m_geometry.allocate(hCells * vCells * 4, hCells * vCells * 6);
                m_geometry.setDrawingMode(GL_TRIANGLES);
                QSGGeometry::TexturedPoint2D *vertices = m_geometry.vertexDataAsTexturedPoint2D();
                ys = yData.data();
                for (int j = 0; j < vCells; ++j, ys += 2) {
                    xs = xData.data();
                    for (int i = 0; i < hCells; ++i, xs += 2) {
                        vertices[0].x = vertices[2].x = xs[0].x;
                        vertices[0].tx = vertices[2].tx = xs[0].tx;
                        vertices[1].x = vertices[3].x = xs[1].x;
                        vertices[1].tx = vertices[3].tx = xs[1].tx;

                        vertices[0].y = vertices[1].y = ys[0].y;
                        vertices[0].ty = vertices[1].ty = ys[0].ty;
                        vertices[2].y = vertices[3].y = ys[1].y;
                        vertices[2].ty = vertices[3].ty = ys[1].ty;

                        vertices += 4;
                    }
                }

                quint16 *indices = m_geometry.indexDataAsUShort();
                for (int i = 0; i < 4 * vCells * hCells; i += 4)
                    appendQuad(&indices, i, i + 1, i + 2, i + 3);
            }
        }
    }
    markDirty(DirtyGeometry);
    m_dirtyGeometry = false;
}
void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGenericNode *node)
{
    if (!node->m_fillNode)
        return;
    if (!(d->effectiveDirty & (DirtyFillGeom | DirtyColor | DirtyFillGradient)))
        return;

    // Make a copy of the data that will be accessed by the material on
    // the render thread. This must be done even when we bail out below.
    QQuickShapeGenericStrokeFillNode *n = node->m_fillNode;
    updateShadowDataInNode(d, n);

    QSGGeometry *g = n->geometry();
    if (d->fillVertices.isEmpty()) {
        if (g->vertexCount() || g->indexCount()) {
            g->allocate(0, 0);
            n->markDirty(QSGNode::DirtyGeometry);
        }
        return;
    }

    if (d->fillGradientActive) {
        QQuickShapeGenericStrokeFillNode::Material gradMat;
        switch (d->fillGradientActive) {
        case LinearGradient:
            gradMat = QQuickShapeGenericStrokeFillNode::MatLinearGradient;
            break;
        case RadialGradient:
            gradMat = QQuickShapeGenericStrokeFillNode::MatRadialGradient;
            break;
        case ConicalGradient:
            gradMat = QQuickShapeGenericStrokeFillNode::MatConicalGradient;
            break;
        default:
            Q_UNREACHABLE();
        }
        n->activateMaterial(m_item->window(), gradMat);
        if (d->effectiveDirty & DirtyFillGradient) {
            // Gradients are implemented via a texture-based material.
            n->markDirty(QSGNode::DirtyMaterial);
            // stop here if only the gradient changed; no need to touch the geometry
            if (!(d->effectiveDirty & DirtyFillGeom))
                return;
        }
    } else {
        n->activateMaterial(m_item->window(), QQuickShapeGenericStrokeFillNode::MatSolidColor);
        // fast path for updating only color values when no change in vertex positions
        if ((d->effectiveDirty & DirtyColor) && !(d->effectiveDirty & DirtyFillGeom)) {
            ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(g->vertexData());
            for (int i = 0; i < g->vertexCount(); ++i)
                vdst[i].set(vdst[i].x, vdst[i].y, d->fillColor);
            n->markDirty(QSGNode::DirtyGeometry);
            return;
        }
    }

    const int indexCount = d->indexType == QSGGeometry::UnsignedShortType
            ? d->fillIndices.count() * 2 : d->fillIndices.count();
    if (g->indexType() != d->indexType) {
        g = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(),
                            d->fillVertices.count(), indexCount, d->indexType);
        n->setGeometry(g);
    } else {
        g->allocate(d->fillVertices.count(), indexCount);
    }
    g->setDrawingMode(QSGGeometry::DrawTriangles);
    memcpy(g->vertexData(), d->fillVertices.constData(), g->vertexCount() * g->sizeOfVertex());
    memcpy(g->indexData(), d->fillIndices.constData(), g->indexCount() * g->sizeOfIndex());

    n->markDirty(QSGNode::DirtyGeometry);
}
QQuickShaderEffectNode* QQuickCustomParticle::buildCustomNodes()
{
    if (QOpenGLContext::currentContext()->isOpenGLES() && m_count * 4 > 0xffff) {
        printf("CustomParticle: Too many particles... \n");
        return 0;
    }

    if (m_count <= 0) {
        printf("CustomParticle: Too few particles... \n");
        return 0;
    }

    if (m_groups.isEmpty())
        return 0;

    QQuickShaderEffectNode *rootNode = 0;
    QQuickShaderEffectMaterial *material = new QQuickShaderEffectMaterial;
    m_dirtyProgram = true;

    foreach (const QString &str, m_groups){
        int gIdx = m_system->groupIds[str];
        int count = m_system->groupData[gIdx]->size();

        QQuickShaderEffectNode* node = new QQuickShaderEffectNode();
        m_nodes.insert(gIdx, node);

        node->setMaterial(material);

        //Create Particle Geometry
        int vCount = count * 4;
        int iCount = count * 6;
        QSGGeometry *g = new QSGGeometry(PlainParticle_AttributeSet, vCount, iCount);
        g->setDrawingMode(GL_TRIANGLES);
        node->setGeometry(g);
        node->setFlag(QSGNode::OwnsGeometry, true);
        PlainVertex *vertices = (PlainVertex *) g->vertexData();
        for (int p=0; p < count; ++p) {
            commit(gIdx, p);
            vertices[0].tx = 0;
            vertices[0].ty = 0;

            vertices[1].tx = 1;
            vertices[1].ty = 0;

            vertices[2].tx = 0;
            vertices[2].ty = 1;

            vertices[3].tx = 1;
            vertices[3].ty = 1;
            vertices += 4;
        }
        quint16 *indices = g->indexDataAsUShort();
        for (int i=0; i < count; ++i) {
            int o = i * 4;
            indices[0] = o;
            indices[1] = o + 1;
            indices[2] = o + 2;
            indices[3] = o + 1;
            indices[4] = o + 3;
            indices[5] = o + 2;
            indices += 6;
        }
    }
예제 #24
0
QSGGeometry *QSGBasicInternalImageNode::updateGeometry(const QRectF &targetRect,
                                               const QRectF &innerTargetRect,
                                               const QRectF &sourceRect,
                                               const QRectF &innerSourceRect,
                                               const QRectF &subSourceRect,
                                               QSGGeometry *geometry,
                                               bool mirror,
                                               bool antialiasing)
{
    int floorLeft = qFloor(subSourceRect.left());
    int ceilRight = qCeil(subSourceRect.right());
    int floorTop = qFloor(subSourceRect.top());
    int ceilBottom = qCeil(subSourceRect.bottom());
    int hTiles = ceilRight - floorLeft;
    int vTiles = ceilBottom - floorTop;

    int hCells = hTiles;
    int vCells = vTiles;
    if (innerTargetRect.width() == 0)
        hCells = 0;
    if (innerTargetRect.left() != targetRect.left())
        ++hCells;
    if (innerTargetRect.right() != targetRect.right())
        ++hCells;
    if (innerTargetRect.height() == 0)
        vCells = 0;
    if (innerTargetRect.top() != targetRect.top())
        ++vCells;
    if (innerTargetRect.bottom() != targetRect.bottom())
        ++vCells;
    QVarLengthArray<X, 32> xData(2 * hCells);
    QVarLengthArray<Y, 32> yData(2 * vCells);
    X *xs = xData.data();
    Y *ys = yData.data();

    if (innerTargetRect.left() != targetRect.left()) {
        xs[0].x = targetRect.left();
        xs[0].tx = sourceRect.left();
        xs[1].x = innerTargetRect.left();
        xs[1].tx = innerSourceRect.left();
        xs += 2;
    }
    if (innerTargetRect.width() != 0) {
        xs[0].x = innerTargetRect.left();
        xs[0].tx = innerSourceRect.x() + (subSourceRect.left() - floorLeft) * innerSourceRect.width();
        ++xs;
        float b = innerTargetRect.width() / subSourceRect.width();
        float a = innerTargetRect.x() - subSourceRect.x() * b;
        for (int i = floorLeft + 1; i <= ceilRight - 1; ++i) {
            xs[0].x = xs[1].x = a + b * i;
            xs[0].tx = innerSourceRect.right();
            xs[1].tx = innerSourceRect.left();
            xs += 2;
        }
        xs[0].x = innerTargetRect.right();
        xs[0].tx = innerSourceRect.x() + (subSourceRect.right() - ceilRight + 1) * innerSourceRect.width();
        ++xs;
    }
    if (innerTargetRect.right() != targetRect.right()) {
        xs[0].x = innerTargetRect.right();
        xs[0].tx = innerSourceRect.right();
        xs[1].x = targetRect.right();
        xs[1].tx = sourceRect.right();
        xs += 2;
    }
    Q_ASSERT(xs == xData.data() + xData.size());
    if (mirror) {
        float leftPlusRight = targetRect.left() + targetRect.right();
        int count = xData.size();
        xs = xData.data();
        for (int i = 0; i < count >> 1; ++i)
            qSwap(xs[i], xs[count - 1 - i]);
        for (int i = 0; i < count; ++i)
            xs[i].x = leftPlusRight - xs[i].x;
    }

    if (innerTargetRect.top() != targetRect.top()) {
        ys[0].y = targetRect.top();
        ys[0].ty = sourceRect.top();
        ys[1].y = innerTargetRect.top();
        ys[1].ty = innerSourceRect.top();
        ys += 2;
    }
    if (innerTargetRect.height() != 0) {
        ys[0].y = innerTargetRect.top();
        ys[0].ty = innerSourceRect.y() + (subSourceRect.top() - floorTop) * innerSourceRect.height();
        ++ys;
        float b = innerTargetRect.height() / subSourceRect.height();
        float a = innerTargetRect.y() - subSourceRect.y() * b;
        for (int i = floorTop + 1; i <= ceilBottom - 1; ++i) {
            ys[0].y = ys[1].y = a + b * i;
            ys[0].ty = innerSourceRect.bottom();
            ys[1].ty = innerSourceRect.top();
            ys += 2;
        }
        ys[0].y = innerTargetRect.bottom();
        ys[0].ty = innerSourceRect.y() + (subSourceRect.bottom() - ceilBottom + 1) * innerSourceRect.height();
        ++ys;
    }
    if (innerTargetRect.bottom() != targetRect.bottom()) {
        ys[0].y = innerTargetRect.bottom();
        ys[0].ty = innerSourceRect.bottom();
        ys[1].y = targetRect.bottom();
        ys[1].ty = sourceRect.bottom();
        ys += 2;
    }
    Q_ASSERT(ys == yData.data() + yData.size());

    if (antialiasing) {
        QSGGeometry *g = geometry;
        Q_ASSERT(g);

        g->allocate(hCells * vCells * 4 + (hCells + vCells - 1) * 4,
                    hCells * vCells * 6 + (hCells + vCells) * 12);
        g->setDrawingMode(QSGGeometry::DrawTriangles);
        SmoothVertex *vertices = reinterpret_cast<SmoothVertex *>(g->vertexData());
        memset(vertices, 0, g->vertexCount() * g->sizeOfVertex());
        quint16 *indices = g->indexDataAsUShort();

        // The deltas are how much the fuzziness can reach into the image.
        // Only the border vertices are moved by the vertex shader, so the fuzziness
        // can't reach further into the image than the closest interior vertices.
        float leftDx = xData.at(1).x - xData.at(0).x;
        float rightDx = xData.at(xData.size() - 1).x - xData.at(xData.size() - 2).x;
        float topDy = yData.at(1).y - yData.at(0).y;
        float bottomDy = yData.at(yData.size() - 1).y - yData.at(yData.size() - 2).y;

        float leftDu = xData.at(1).tx - xData.at(0).tx;
        float rightDu = xData.at(xData.size() - 1).tx - xData.at(xData.size() - 2).tx;
        float topDv = yData.at(1).ty - yData.at(0).ty;
        float bottomDv = yData.at(yData.size() - 1).ty - yData.at(yData.size() - 2).ty;

        if (hCells == 1) {
            leftDx = rightDx *= 0.5f;
            leftDu = rightDu *= 0.5f;
        }
        if (vCells == 1) {
            topDy = bottomDy *= 0.5f;
            topDv = bottomDv *= 0.5f;
        }

        // This delta is how much the fuzziness can reach out from the image.
        float delta = float(qAbs(targetRect.width()) < qAbs(targetRect.height())
                            ? targetRect.width() : targetRect.height()) * 0.5f;

        quint16 index = 0;
        ys = yData.data();
        for (int j = 0; j < vCells; ++j, ys += 2) {
            xs = xData.data();
            bool isTop = j == 0;
            bool isBottom = j == vCells - 1;
            for (int i = 0; i < hCells; ++i, xs += 2) {
                bool isLeft = i == 0;
                bool isRight = i == hCells - 1;

                SmoothVertex *v = vertices + index;

                quint16 topLeft = index;
                for (int k = (isTop || isLeft ? 2 : 1); k--; ++v, ++index) {
                    v->x = xs[0].x;
                    v->u = xs[0].tx;
                    v->y = ys[0].y;
                    v->v = ys[0].ty;
                }

                quint16 topRight = index;
                for (int k = (isTop || isRight ? 2 : 1); k--; ++v, ++index) {
                    v->x = xs[1].x;
                    v->u = xs[1].tx;
                    v->y = ys[0].y;
                    v->v = ys[0].ty;
                }

                quint16 bottomLeft = index;
                for (int k = (isBottom || isLeft ? 2 : 1); k--; ++v, ++index) {
                    v->x = xs[0].x;
                    v->u = xs[0].tx;
                    v->y = ys[1].y;
                    v->v = ys[1].ty;
                }

                quint16 bottomRight = index;
                for (int k = (isBottom || isRight ? 2 : 1); k--; ++v, ++index) {
                    v->x = xs[1].x;
                    v->u = xs[1].tx;
                    v->y = ys[1].y;
                    v->v = ys[1].ty;
                }

                appendQuad(&indices, topLeft, topRight, bottomLeft, bottomRight);

                if (isTop) {
                    vertices[topLeft].dy = vertices[topRight].dy = topDy;
                    vertices[topLeft].dv = vertices[topRight].dv = topDv;
                    vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -delta;
                    appendQuad(&indices, topLeft + 1, topRight + 1, topLeft, topRight);
                }

                if (isBottom) {
                    vertices[bottomLeft].dy = vertices[bottomRight].dy = -bottomDy;
                    vertices[bottomLeft].dv = vertices[bottomRight].dv = -bottomDv;
                    vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = delta;
                    appendQuad(&indices, bottomLeft, bottomRight, bottomLeft + 1, bottomRight + 1);
                }

                if (isLeft) {
                    vertices[topLeft].dx = vertices[bottomLeft].dx = leftDx;
                    vertices[topLeft].du = vertices[bottomLeft].du = leftDu;
                    vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -delta;
                    appendQuad(&indices, topLeft + 1, topLeft, bottomLeft + 1, bottomLeft);
                }

                if (isRight) {
                    vertices[topRight].dx = vertices[bottomRight].dx = -rightDx;
                    vertices[topRight].du = vertices[bottomRight].du = -rightDu;
                    vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = delta;
                    appendQuad(&indices, topRight, topRight + 1, bottomRight, bottomRight + 1);
                }
            }
        }

        Q_ASSERT(index == g->vertexCount());
        Q_ASSERT(indices - g->indexCount() == g->indexData());
    } else {
        if (!geometry) {
            geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(),
                                       hCells * vCells * 4, hCells * vCells * 6,
                                       QSGGeometry::UnsignedShortType);
        } else {
            geometry->allocate(hCells * vCells * 4, hCells * vCells * 6);
        }
        geometry->setDrawingMode(QSGGeometry::DrawTriangles);
        QSGGeometry::TexturedPoint2D *vertices = geometry->vertexDataAsTexturedPoint2D();
        ys = yData.data();
        for (int j = 0; j < vCells; ++j, ys += 2) {
            xs = xData.data();
            for (int i = 0; i < hCells; ++i, xs += 2) {
                vertices[0].x = vertices[2].x = xs[0].x;
                vertices[0].tx = vertices[2].tx = xs[0].tx;
                vertices[1].x = vertices[3].x = xs[1].x;
                vertices[1].tx = vertices[3].tx = xs[1].tx;

                vertices[0].y = vertices[1].y = ys[0].y;
                vertices[0].ty = vertices[1].ty = ys[0].ty;
                vertices[2].y = vertices[3].y = ys[1].y;
                vertices[2].ty = vertices[3].ty = ys[1].ty;

                vertices += 4;
            }
        }

        quint16 *indices = geometry->indexDataAsUShort();
        for (int i = 0; i < 4 * vCells * hCells; i += 4)
            appendQuad(&indices, i, i + 1, i + 2, i + 3);
    }
    return geometry;
}
예제 #25
0
void QSGBasicInternalImageNode::updateGeometry()
{
    Q_ASSERT(!m_targetRect.isEmpty());
    const QSGTexture *t = materialTexture();
    if (!t) {
        QSGGeometry *g = geometry();
        g->allocate(4);
        g->setDrawingMode(QSGGeometry::DrawTriangleStrip);
        memset(g->vertexData(), 0, g->sizeOfVertex() * 4);
    } else {
        QRectF sourceRect = t->normalizedTextureSubRect();

        QRectF innerSourceRect(sourceRect.x() + m_innerSourceRect.x() * sourceRect.width(),
                               sourceRect.y() + m_innerSourceRect.y() * sourceRect.height(),
                               m_innerSourceRect.width() * sourceRect.width(),
                               m_innerSourceRect.height() * sourceRect.height());

        bool hasMargins = m_targetRect != m_innerTargetRect;

        int floorLeft = qFloor(m_subSourceRect.left());
        int ceilRight = qCeil(m_subSourceRect.right());
        int floorTop = qFloor(m_subSourceRect.top());
        int ceilBottom = qCeil(m_subSourceRect.bottom());
        int hTiles = ceilRight - floorLeft;
        int vTiles = ceilBottom - floorTop;

        bool hasTiles = hTiles != 1 || vTiles != 1;
        bool fullTexture = innerSourceRect == QRectF(0, 0, 1, 1);

        // An image can be rendered as a single quad if:
        // - There are no margins, and either:
        //   - the image isn't repeated
        //   - the source rectangle fills the entire texture so that texture wrapping can be used,
        //     and NPOT is supported
        if (!hasMargins && (!hasTiles || (fullTexture && supportsWrap(t->textureSize())))) {
            QRectF sr;
            if (!fullTexture) {
                sr = QRectF(innerSourceRect.x() + (m_subSourceRect.left() - floorLeft) * innerSourceRect.width(),
                            innerSourceRect.y() + (m_subSourceRect.top() - floorTop) * innerSourceRect.height(),
                            m_subSourceRect.width() * innerSourceRect.width(),
                            m_subSourceRect.height() * innerSourceRect.height());
            } else {
                sr = QRectF(m_subSourceRect.left() - floorLeft, m_subSourceRect.top() - floorTop,
                            m_subSourceRect.width(), m_subSourceRect.height());
            }
            if (m_mirror) {
                qreal oldLeft = sr.left();
                sr.setLeft(sr.right());
                sr.setRight(oldLeft);
            }

            if (m_antialiasing) {
                QSGGeometry *g = geometry();
                Q_ASSERT(g != &m_geometry);
                g->allocate(8, 14);
                g->setDrawingMode(QSGGeometry::DrawTriangleStrip);
                SmoothVertex *vertices = reinterpret_cast<SmoothVertex *>(g->vertexData());
                float delta = float(qAbs(m_targetRect.width()) < qAbs(m_targetRect.height())
                        ? m_targetRect.width() : m_targetRect.height()) * 0.5f;
                float sx = float(sr.width() / m_targetRect.width());
                float sy = float(sr.height() / m_targetRect.height());
                for (int d = -1; d <= 1; d += 2) {
                    for (int j = 0; j < 2; ++j) {
                        for (int i = 0; i < 2; ++i, ++vertices) {
                            vertices->x = m_targetRect.x() + i * m_targetRect.width();
                            vertices->y = m_targetRect.y() + j * m_targetRect.height();
                            vertices->u = sr.x() + i * sr.width();
                            vertices->v = sr.y() + j * sr.height();
                            vertices->dx = (i == 0 ? delta : -delta) * d;
                            vertices->dy = (j == 0 ? delta : -delta) * d;
                            vertices->du = (d < 0 ? 0 : vertices->dx * sx);
                            vertices->dv = (d < 0 ? 0 : vertices->dy * sy);
                        }
                    }
                }
                Q_ASSERT(vertices - g->vertexCount() == g->vertexData());
                static const quint16 indices[] = {
                    0, 4, 1, 5, 3, 7, 2, 6, 0, 4,
                    4, 6, 5, 7
                };
                Q_ASSERT(g->sizeOfIndex() * g->indexCount() == sizeof(indices));
                memcpy(g->indexDataAsUShort(), indices, sizeof(indices));
            } else {
                m_geometry.allocate(4);
                m_geometry.setDrawingMode(QSGGeometry::DrawTriangleStrip);
                QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_targetRect, sr);
            }
        } else {
            QSGGeometry *g = m_antialiasing ? geometry() : &m_geometry;
            updateGeometry(m_targetRect, m_innerTargetRect,
                           sourceRect, innerSourceRect, m_subSourceRect,
                           g, m_mirror, m_antialiasing);
        }
    }
    markDirty(DirtyGeometry);
    m_dirtyGeometry = false;
}
예제 #26
0
QSGNode * DataSetView::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
	if (width() <= 0 || height() <= 0) {
		delete oldNode;
		return 0;
	}

	//if(recalculateCellSizes) calculateCellContentSizes();

	const QRectF rect = boundingRect();


	const int linesPerNode = 1000; //Or something? should be multiple of 2 though

	if(!oldNode)
		oldNode = new QSGNode();

	QSGGeometryNode * currentNode = static_cast<QSGGeometryNode*>(oldNode->firstChild());


	for(int lineIndex=0; lineIndex<_lines.size();)
	{
		if(currentNode == NULL)
		{
			currentNode = new QSGGeometryNode;

			currentNode->setFlag(QSGNode::OwnsMaterial, false);
			currentNode->setFlag(QSGNode::OwnsGeometry, true);
			currentNode->setMaterial(&material);

			oldNode->appendChildNode(currentNode);
		}

		int geomSize = std::min(linesPerNode, (int)(_lines.size() - lineIndex));
		geomSize *= 2;

		QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), geomSize);
		geometry->setLineWidth(1);
		geometry->setDrawingMode(GL_LINES);
		QSGGeometry::Point2D *points = geometry->vertexDataAsPoint2D();

		for(int geomIndex=0; geomIndex<geomSize; geomIndex+=2)
		{
			points[geomIndex  ].x = _lines[lineIndex].first.x() + rect.left();
			points[geomIndex  ].y = _lines[lineIndex].first.y() + rect.top();
			points[geomIndex+1].x = _lines[lineIndex].second.x() + rect.left();
			points[geomIndex+1].y = _lines[lineIndex].second.y() + rect.top();
			lineIndex++;
		}

		currentNode->setGeometry(geometry);

		currentNode = static_cast<QSGGeometryNode*>(currentNode->nextSibling());
	}


	std::queue<QSGGeometryNode*> killThem;

	while(currentNode != NULL) //superfluous children! Lets kill em
	{
		killThem.push(currentNode);
		currentNode = static_cast<QSGGeometryNode*>(currentNode->nextSibling());
	}

	while(killThem.size() > 0)
	{
		QSGGeometryNode * childToDie = killThem.front();
		killThem.pop();

		delete childToDie;
	}


	return oldNode;
}
예제 #27
0
QSGNode *GraphConnection::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
    if (m_source == m_sink)
        return oldNode;

    QSGGeometryNode *node = 0;
    QSGGeometry *geometry = 0;

    QPointF p1, p2, p3, p4;

    p1.setX(m_source.x());
    p1.setY(m_source.y());
    p4.setX(m_sink.x());
    p4.setY(m_sink.y());

    p2.setX(p1.x());
    p3.setX(p4.x());
    if (p1.y() < p4.y()) {
        p2.setY(p1.y() * 0.75 + p4.y() * 0.25);
        p3.setY(p4.y() * 0.75 + p1.y() * 0.25);
    } else {
        p2.setY(p1.y() - (p4.y()-p1.y())*0.25);
        p3.setY(p4.y() + (p4.y()-p1.y())*0.25);
    }

    // quick 'n' dirty estimation of bezier length
    // http://steve.hollasch.net/cgindex/curves/cbezarclen.html
    qreal l1 = (QVector2D(p2)-QVector2D(p1)).length() +
               (QVector2D(p3)-QVector2D(p2)).length() +
               (QVector2D(p4)-QVector2D(p3)).length();
    qreal l0 = (QVector2D(p4)-QVector2D(p1)).length();
    qreal length = 0.5*l0 + 0.5*l1;

    int segmentCount = length;

    if (!oldNode) {
        node = new QSGGeometryNode;
        geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), segmentCount);
        geometry->setLineWidth(2);
        geometry->setDrawingMode(GL_LINE_STRIP);
        node->setGeometry(geometry);
        node->setFlag(QSGNode::OwnsGeometry);
        QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
        material->setColor(QColor(0, 0, 0));
        node->setMaterial(material);
        node->setFlag(QSGNode::OwnsMaterial);
    } else {
        node = static_cast<QSGGeometryNode *>(oldNode);
        geometry = node->geometry();
        geometry->allocate(segmentCount);
    }

    QRectF bounds = boundingRect();
    QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D();
    for (int i = 0; i < segmentCount; ++i) {
        qreal t = i / qreal(segmentCount - 1);
        qreal invt = 1 - t;

        // Bezier
        QPointF pos = invt * invt * invt * p1
                    + 3 * invt * invt * t * p2
                    + 3 * invt * t * t * p3
                    + t * t * t * p4;

        float x = pos.x();
        float y = pos.y();

        vertices[i].set(x, y);
    }

    return node;
}
QSGNode* AudioBarSpectrumItem::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) {
    if (!m_analyzer) return oldNode;
    if (!isVisible()) return oldNode;

    const std::vector<double>& points = m_analyzer->getSimplifiedSpectrum();
    const double gain = m_agcEnabled ? m_analyzer->getAgcValue() : m_manualGain;
    const int pointCount = points.size();
    if (pointCount < 2) return oldNode;

    // -------------------- Prepare QSG Nodes:
    QSGNode* parentNode = nullptr;
    if (oldNode) {
        parentNode = static_cast<QSGNode*>(oldNode);
    } else {
        parentNode = new QSGNode;
    }
    // adapt child count:
    int childCount = parentNode->childCount();
    if (childCount != 2) {
        parentNode->removeAllChildNodes();
        QSGGeometryNode* node = new QSGGeometryNode;
        QSGGeometry* geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 3);
        geometry->setDrawingMode(GL_TRIANGLE_STRIP);
        node->setGeometry(geometry);
        node->setFlag(QSGNode::OwnsGeometry);
        QSGFlatColorMaterial* material = new QSGFlatColorMaterial;
        material->setColor("#fff");
        node->setMaterial(material);
        node->setFlag(QSGNode::OwnsMaterial);
        parentNode->appendChildNode(node);

        // Attention: TODO: colors are swapped!

        node = new QSGGeometryNode;
        geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 3);
        geometry->setDrawingMode(GL_TRIANGLE_STRIP);
        node->setGeometry(geometry);
        node->setFlag(QSGNode::OwnsGeometry);
        material = new QSGFlatColorMaterial;
        material->setColor(m_color);
        node->setMaterial(material);
        node->setFlag(QSGNode::OwnsMaterial);
        parentNode->appendChildNode(node);
    }

    QSGGeometryNode* const qsgNode = static_cast<QSGGeometryNode*>(parentNode->childAtIndex(0));
    QSGGeometryNode* const qsgNodeOutline = static_cast<QSGGeometryNode*>(parentNode->childAtIndex(1));
    if (!qsgNode || !qsgNodeOutline) {
        qCritical() << "[SpectrumItem] Could not get QSG Node.";
        return nullptr;
    }
    QSGGeometry* const geometry = qsgNode->geometry();
    QSGGeometry* const geometryOutline = qsgNodeOutline->geometry();
    if (!geometry || !geometryOutline) {
        qCritical() << "[SpectrumItem] Could not get QSG Geometry.";
        return nullptr;
    }

    const int verticesCount = pointCount * 7;
    const int outlineVerticesCount = pointCount * 7;

    geometry->allocate(verticesCount);
    geometryOutline->allocate(outlineVerticesCount);
    QSGGeometry::Point2D* const vertices = geometry->vertexDataAsPoint2D();
    QSGGeometry::Point2D* const verticesOutline = geometryOutline->vertexDataAsPoint2D();

    if (! vertices || !verticesOutline) {
        qCritical() << "[SpectrumItem] Could not get QSG vertices.";
        return nullptr;
    }

    const double itemWidth = width();
    const double itemHeight = height();
    const double barWidth = (itemWidth / pointCount) * 0.4;
    const double spaceWidth = (itemWidth / pointCount) * 0.6;
    const double endLineHeight = itemHeight / 100.0;

    // draw spectrum:
    for (int i = 0; i < pointCount; ++i) {
        const float x = itemWidth * (i / float(pointCount));
        const float y = itemHeight * (1 - points[i] * gain);

        vertices[i*7].set(x, itemHeight);
        vertices[i*7+1].set(x, y);
        vertices[i*7+2].set(x + barWidth, itemHeight);
        vertices[i*7+3].set(x + barWidth, y);
        vertices[i*7+4].set(x + barWidth, itemHeight);
        vertices[i*7+5].set(x + barWidth, itemHeight);
        vertices[i*7+6].set(x + barWidth + spaceWidth, itemHeight);

        const float y2 = qMin(itemHeight, itemHeight * (1 - points[i] * gain) + endLineHeight);

        verticesOutline[i*7].set(x, itemHeight);
        verticesOutline[i*7+1].set(x, y2);
        verticesOutline[i*7+2].set(x + barWidth, itemHeight);
        verticesOutline[i*7+3].set(x + barWidth, y2);
        verticesOutline[i*7+4].set(x + barWidth, itemHeight);
        verticesOutline[i*7+5].set(x + barWidth, itemHeight);
        verticesOutline[i*7+6].set(x + barWidth + spaceWidth, itemHeight);
    }

    // tell Scene Graph that this items needs to be drawn:
    qsgNode->markDirty(QSGNode::DirtyGeometry);
    qsgNodeOutline->markDirty(QSGNode::DirtyGeometry);

    return parentNode;
}
예제 #29
0
QSGNode* OMX_MediaProcessorElement::updatePaintNode(QSGNode*, UpdatePaintNodeData*)
{
    if (!m_texProvider) {
        m_texProvider = new OMX_TextureProviderQQuickItem(this);
        m_mediaProc   = new OMX_MediaProcessor(m_texProvider);
        connect(m_mediaProc, SIGNAL(playbackCompleted()), this, SIGNAL(playbackCompleted()));
        connect(m_mediaProc, SIGNAL(playbackStarted()), this, SIGNAL(playbackStarted()));

        // Open if filepath is set.
        // TODO: Handle errors.
        if (!m_source.isNull()) {
            //if (QFile(m_source).exists()) {
                if (openMedia(m_source))
                    m_mediaProc->play();
            //}
            //else {
                LOG_WARNING(LOG_TAG, "File does not exist.");
            //}
        }
    }

    return NULL;

#if 0
    QSGGeometryNode* node = 0;
    QSGGeometry* geometry = 0;

    if (!oldNode) {
        // Create the node.
        node = new QSGGeometryNode;
        geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
        geometry->setDrawingMode(GL_TRIANGLE_STRIP);
        node->setGeometry(geometry);
        node->setFlag(QSGNode::OwnsGeometry);

        // TODO: Who is freeing this?
        // TODO: I cannot know the texture size here.
        QSGOpaqueTextureMaterial* material = new QSGOpaqueTextureMaterial;
        m_sgtexture = new OMX_SGTexture(m_texture, QSize(1920, 1080));
        material->setTexture(m_sgtexture);
        node->setMaterial(material);
        node->setFlag(QSGNode::OwnsMaterial);

#ifdef ENABLE_VIDEO_PROCESSOR
        QPlatformNativeInterface* nativeInterface =
                QGuiApplicationPrivate::platformIntegration()->nativeInterface();
        Q_ASSERT(nativeInterface);
        EGLDisplay eglDisplay = nativeInterface->nativeResourceForIntegration("egldisplay");
        EGLContext eglContext = nativeInterface->nativeResourceForContext(
                    "eglcontext",
                    QOpenGLContext::currentContext()
                    );
#endif

        // Provider MUST be built in this thread.
        m_provider  = new OMX_TextureProviderQQuickItem(this);
#ifdef ENABLE_VIDEO_PROCESSOR
        m_videoProc = new OMX_VideoProcessor(eglDisplay, eglContext, m_provider);
        connect(m_videoProc, SIGNAL(textureReady(uint)), this, SLOT(onTextureChanged(uint)));
        if (!m_source.isNull())
            m_videoProc->setVideoPath(m_source);
        if (m_playScheduled) {
            m_timer->start(30);
            m_videoProc->play();
        }
#elif ENABLE_MEDIA_PROCESSOR
        LOG_VERBOSE(LOG_TAG, "Starting video using media processor...");
        m_mediaProc = new OMX_MediaProcessor(m_provider);
        m_mediaProc->setFilename("/home/pi/usb/Cars2.mkv", m_texture);
        //if (m_playScheduled) {
            m_timer->start(40);
            m_mediaProc->play();
        //}
#else
        LOG_VERBOSE(LOG_TAG, "Starting video...");
        QtConcurrent::run(&startVideo, m_provider, this);
        m_timer->start(30);
#endif
    }
    else {
        node = static_cast<QSGGeometryNode*>(oldNode);
        geometry = node->geometry();
        geometry->allocate(4);

        // Update texture in the node if needed.
        QSGOpaqueTextureMaterial* material = (QSGOpaqueTextureMaterial*)node->material();
        if (m_texture != (GLuint)material->texture()->textureId()) {
            // TODO: Does setTextureId frees the prev texture?
            // TODO: I should the given the texture size.
            LOG_ERROR(LOG_TAG, "Updating texture to %u!", m_texture);
            material = new QSGOpaqueTextureMaterial;
            m_sgtexture->setTexture(m_texture, QSize(1920, 1080));
        }
    }

    // Create the vertices and map to texture.
    QRectF bounds = boundingRect();
    QSGGeometry::TexturedPoint2D* vertices = geometry->vertexDataAsTexturedPoint2D();
    vertices[0].set(bounds.x(), bounds.y() + bounds.height(), 0.0f, 0.0f);
    vertices[1].set(bounds.x() + bounds.width(), bounds.y() + bounds.height(), 1.0f, 0.0f);
    vertices[2].set(bounds.x(), bounds.y(), 0.0f, 1.0f);
    vertices[3].set(bounds.x() + bounds.width(), bounds.y(), 1.0f, 1.0f);
    return node;
#endif
}
QSGNode* NodeConnectionLines::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) {
    if (!m_nodeObject) return nullptr;
    const QVector<QPointer<NodeBase>>& connectedNodes = m_nodeObject->getConnectedNodes();
    int connectionCount = connectedNodes.size();

    // -------------------- Prepare QSG Nodes:
    QSGNode* parentNode = oldNode;
    if (!oldNode) {
        parentNode = new QSGNode();
    } else {
        // update color in case it changed:
        // FIXME: is there a more efficient way to do this?
        for (int i=0; i<parentNode->childCount(); ++i) {
            QSGGeometryNode* childNode = static_cast<QSGGeometryNode*>(parentNode->childAtIndex(i));
            if (!childNode) continue;
            QSGFlatColorMaterial* material = static_cast<QSGFlatColorMaterial*>(childNode->material());
            if (!material) continue;
            material->setColor(m_color);
        }
    }
    // adapt child count:
    int childCount = parentNode->childCount();
    if (childCount < connectionCount) {
        for (int i=0; i<(connectionCount - childCount); ++i) {
            QSGGeometryNode* node = new QSGGeometryNode;
            QSGGeometry* geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 3);
            geometry->setDrawingMode(GL_TRIANGLE_STRIP);
            node->setGeometry(geometry);
            node->setFlag(QSGNode::OwnsGeometry);
            QSGFlatColorMaterial* material = new QSGFlatColorMaterial;
            material->setColor(m_color);
            node->setMaterial(material);
            node->setFlag(QSGNode::OwnsMaterial);
            parentNode->appendChildNode(node);
        }
    } else if (childCount > connectionCount) {
        for (int i=0; i<(childCount - connectionCount); ++i) {
            parentNode->removeChildNode(parentNode->childAtIndex(0));
        }
    }
    Q_ASSERT(parentNode->childCount() == connectionCount);

    // calculate common start point:
    const QPointF p0(width(), height() / 2);
    double widthOffset = m_lineWidth / 2;
    //const QPointF posInScene = mapToScene(QPointF(0, 0));


    for (int i=0; i<connectionCount; ++i) {
        NodeBase* otherNode = connectedNodes[i];
        if (!otherNode) continue;
        QQuickItem* otherGuiItem = otherNode->getGuiItem();
        if (!otherGuiItem) continue;
        const QPointF p3 = mapFromItem(otherGuiItem, QPointF(-otherGuiItem->width() / 2, otherGuiItem->height() / 2));
        int handleLength = std::max(50, std::min(int(p3.x() - p0.x()), 80));
        const QPointF p1(p0.x() + handleLength, p0.y());
        const QPointF p2(p3.x() - handleLength, p3.y());

        // calculate reasonable segment count:
        int segmentCount = qMax(16.0, qMin(qAbs(p3.y() - p0.y()) / 25, 50.0));
        int verticesCount = segmentCount * 2;

        QSGGeometryNode* qsgNode = static_cast<QSGGeometryNode*>(parentNode->childAtIndex(i));
        if (!qsgNode) continue;

        QSGGeometry* geometry = qsgNode->geometry();
        if (!geometry) continue;
        geometry->allocate(verticesCount);
        QSGGeometry::Point2D* vertices = geometry->vertexDataAsPoint2D();

        // triangulate cubic bezier curve:
        for (int i = 0; i < segmentCount; ++i) {
            // t is the position on the line:
            const qreal t = i / qreal(segmentCount - 1);

            // pos is the point on the curve at "t":
            const QPointF pos = calculateBezierPoint(t, p0, p1, p2, p3);

            // normal is the normal vector at that point
            const QPointF normal = normalFromTangent(calculateBezierTangent(t, p0, p1, p2, p3));

            // first is a point offsetted in the normal direction by lineWidth / 2 from pos
            const QPointF first = pos - normal * widthOffset;

            // ssecond is a point offsetted in the negative normal direction by lineWidth / 2 from pos
            const QPointF second = pos + normal * widthOffset;

            // add first and second as vertices to this geometry:
            vertices[i*2].set(first.x(), first.y());
            vertices[i*2+1].set(second.x(), second.y());
        }

        // tell Scene Graph that this items needs to be drawn:
        qsgNode->markDirty(QSGNode::DirtyGeometry);
    }

    return parentNode;
}