--- D:/Développement/Qt/Qt3DTestPath/qtext3dgeometry_org.cpp jeu. janv. 5 01:43:22 2017 +++ D:/Développement/Qt/Qt3DTestPath/qtext3dgeometry.cpp jeu. janv. 5 02:12:10 2017 @@ -26,6 +26,7 @@ struct TriangulationData { QVector vertices; QVector indices; QVector outlines; + QVector outlineindices; bool inverted; }; @@ -33,45 +34,53 @@ TriangulationData triangulate(const QString &text, { TriangulationData result; - QVector advances; - { - QRawFont rawFont = QRawFont::fromFont(font); - auto indexes = rawFont.glyphIndexesForString(text); - - advances.resize(indexes.size()); - - if(!rawFont.advancesForGlyphIndexes(indexes.data(), advances.data(), indexes.size(), QRawFont::SeparateAdvances)) - qCritical() << "Unable to get necessary glyph information"; - } - int beginOutline = 0; - int advancesIndex = 0; - QPointF curAdvance(0, 0); bool isInvertedDetected = false; - for(QChar c : text) { QPainterPath path; - path.addText(0, 0, font, c); + path.setFillRule(Qt::WindingFill); + path.addText(0, 0, font, text); + QList polygons = path.toSubpathPolygons(QTransform().scale(1.f, -1.f)); // maybe glyph has no geometry if(polygons.size() == 0) - continue; + return result; const int prevNumIndices = result.indices.size(); path = QPainterPath(); + path.setFillRule(Qt::WindingFill); for(QPolygonF &p : polygons) { path.addPolygon(p); + } - int endOutline = beginOutline + p.size() - 1; - result.outlines.push_back({beginOutline, endOutline}); - beginOutline = endOutline; + QPolylineSet polylines = qPolyline(path, QTransform(), 1.0f); + + QVector tempIndices; + tempIndices.resize(polylines.indices.size()); + memcpy(&tempIndices[0], polylines.indices.data(), polylines.indices.size() * sizeof(unsigned short)); + + int lastindice = 0; + for (int i = 0; i < tempIndices.size(); i++) + { + if (tempIndices[i] == USHRT_MAX /* -1 in qtriangulator_p.h */ ) { + int endOutline = lastindice; + result.outlines.push_back({beginOutline, endOutline}); + //qDebug() << "beginOutline: " << beginOutline << ", endOutline: " << endOutline; + beginOutline = endOutline; + } + else + { + result.outlineindices.push_back(tempIndices[i]); + lastindice++; + } } + //qDebug() << "Indices: " << result.outlineindices.size() << result.outlineindices; - QTriangleSet triangles = qTriangulate(path); + QTriangleSet triangles = qTriangulate(path, QTransform(), 1.0f); result.indices.resize(result.indices.size() + triangles.indices.size()); memcpy(&result.indices[prevNumIndices], triangles.indices.data(), triangles.indices.size() * sizeof(unsigned short)); @@ -80,7 +89,7 @@ TriangulationData triangulate(const QString &text, result.vertices.reserve(triangles.vertices.size() / 2); for(int i = 0; i < triangles.vertices.size(); i += 2) - result.vertices.push_back(QVector3D((triangles.vertices[i] + curAdvance.x()) / font.pointSizeF(), (triangles.vertices[i+1] + curAdvance.y()) / font.pointSizeF(), 0)); + result.vertices.push_back(QVector3D(triangles.vertices[i] / font.pointSizeF(), triangles.vertices[i+1] / font.pointSizeF(), 0)); if(!isInvertedDetected) { @@ -119,7 +128,7 @@ TriangulationData triangulate(const QString &text, { result.inverted = false; // isInvertedDetected stays false - qDebug() << "triangulate text: exstrusion direction was not found! falling back to default: no invert"; + qDebug() << "triangulate text: extrusion direction was not found! falling back to default: no invert"; break; } else @@ -135,7 +144,6 @@ TriangulationData triangulate(const QString &text, } } - curAdvance += advances[advancesIndex++]; } return result; @@ -236,7 +244,9 @@ void QText3DGeometry::updateVertices() const int numVertices = data.vertices.size(); const int numIndices = data.indices.size(); - //qDebug() << numVertices << numIndices << numOutlines; + /*qDebug() << d->m_text << d->m_font.family() << numVertices << numIndices + << data.outlines.size() << data.outlineindices.size() + << (data.inverted ? "Inverted" : "Normal");*/ using Index = unsigned short; struct Vertex { @@ -268,24 +278,21 @@ void QText3DGeometry::updateVertices() const int end = data.outlines[i].end; const int verticesIndexBegin = verticesIndex; - QVector3D prevNormal = QVector3D::crossProduct(vertices[end - 1 + numVertices].position - vertices[end - 1].position - , vertices[begin].position - vertices[end - 1].position).normalized(); - if(data.inverted) - prevNormal = -prevNormal; + QVector3D prevNormal = QVector3D::crossProduct(vertices[data.outlineindices[end - 1] + numVertices].position - vertices[data.outlineindices[end - 1]].position + , vertices[data.outlineindices[begin]].position - vertices[data.outlineindices[end - 1]].position).normalized(); for(int j = begin; j < end; j++) { const bool isLastIndex = j == end - 1; - const int cur = j; - const int next = ((j - begin + 1) % (end - begin)) + begin; // normalize, bring in range and adjust + const int cur = data.outlineindices[j]; + const int next = data.outlineindices[((j - begin + 1) % (end - begin)) + begin]; // normalize, bring in range and adjust + QVector3D normal = QVector3D::crossProduct(vertices[cur + numVertices].position - vertices[cur].position , vertices[next].position - vertices[cur].position).normalized(); - if(data.inverted) - normal = -normal; // use smooth normals in case of a short angle bool smooth = QVector3D::dotProduct(prevNormal, normal) > (90.f - d->m_smoothAngle) / 90.f; - const QVector3D resultNormal = smooth ? mix(prevNormal, resultNormal, .5f) : normal; + const QVector3D resultNormal = smooth ? mix(prevNormal, normal, .5f) : normal; if(!smooth) { vertices.push_back({vertices[cur].position, prevNormal}); @@ -301,24 +308,12 @@ void QText3DGeometry::updateVertices() const int v2 = isLastIndex ? verticesIndexBegin : verticesIndex + 2; const int v3 = isLastIndex ? verticesIndexBegin + 1 : verticesIndex + 3; - if(data.inverted) - { - indices.push_back(v0); - indices.push_back(v2); - indices.push_back(v1); - indices.push_back(v2); - indices.push_back(v3); - indices.push_back(v1); - } - else - { - indices.push_back(v0); - indices.push_back(v1); - indices.push_back(v2); - indices.push_back(v2); - indices.push_back(v1); - indices.push_back(v3); - } + indices.push_back(v0); + indices.push_back(v1); + indices.push_back(v2); + indices.push_back(v2); + indices.push_back(v1); + indices.push_back(v3); verticesIndex += 2; prevNormal = normal;