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); }
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); }
/* * The function hardcodes a fixed set of grid lines and scales * those to the bounding rect. */ void GridNode::setRect(const QRectF &rect) { int vCount = int((rect.width() - 1) / GRID_SIZE); int hCount = int((rect.height() - 1) / GRID_SIZE); int lineCount = vCount + hCount; QSGGeometry *g = geometry(); g->allocate(lineCount * 2); float x = rect.x(); float y = rect.y(); float w = rect.width(); float h = rect.height(); QSGGeometry::Point2D *v = g->vertexDataAsPoint2D(); // Then write the vertical lines for (int i=0; i<vCount; ++i) { float dx = (i + 1) * GRID_SIZE; v[i*2].set(dx, y); v[i*2+1].set(dx, y + h); } v += vCount * 2; // Then write the horizontal lines for (int i=0; i<hCount; ++i) { float dy = (i + 1) * GRID_SIZE; v[i*2].set(x, dy); v[i*2+1].set(x + w, dy); } // Tell the scenegraph we updated the geometry.. markDirty(QSGNode::DirtyGeometry); }
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; }
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); }
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); }
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; }
//! [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); }
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); }
void VideoNode::updateGeometry(const PaintAreas & areas) { QSGGeometry *g = geometry(); if (m_materialType == MaterialTypeVideo) { if (!m_validGeometry) g = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4); QSGGeometry::TexturedPoint2D *v = g->vertexDataAsTexturedPoint2D(); // Set geometry first setGeom(v + 0, areas.videoArea.topLeft()); setGeom(v + 1, areas.videoArea.bottomLeft()); setGeom(v + 2, areas.videoArea.topRight()); setGeom(v + 3, areas.videoArea.bottomRight()); // and then texture coordinates setTex(v + 0, areas.sourceRect.topLeft()); setTex(v + 1, areas.sourceRect.bottomLeft()); setTex(v + 2, areas.sourceRect.topRight()); setTex(v + 3, areas.sourceRect.bottomRight()); } else { if (!m_validGeometry) g = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4); QSGGeometry::Point2D *v = g->vertexDataAsPoint2D(); setGeom(v + 0, areas.videoArea.topLeft()); setGeom(v + 1, areas.videoArea.bottomLeft()); setGeom(v + 2, areas.videoArea.topRight()); setGeom(v + 3, areas.videoArea.bottomRight()); } if (!m_validGeometry) { setGeometry(g); m_validGeometry = true; } markDirty(DirtyGeometry); }
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; }
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 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); }
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; }
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; }
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; }