void PolygonNode::calcFillVertexes(const VertexDataPtr& pVertexData, Pixel32 color) { if (getNumDifferentPts(m_Pts) < 3) { return; } // Remove duplicate points vector<glm::vec2> pts; vector<unsigned int> holeIndexes; pts.reserve(m_Pts.size()); if (glm::distance2(m_Pts[0], m_Pts[m_Pts.size()-1]) > 0.1) { pts.push_back(m_Pts[0]); } for (unsigned i = 1; i < m_Pts.size(); ++i) { if (glm::distance2(m_Pts[i], m_Pts[i-1]) > 0.1) { pts.push_back(m_Pts[i]); } } if (m_Holes.size() > 0) { for (unsigned int i = 0; i < m_Holes.size(); i++) { //loop over collection holeIndexes.push_back(pts.size()); for (unsigned int j = 0; j < m_Holes[i].size(); j++) { //loop over vector pts.push_back(m_Holes[i][j]); } } } if (color.getA() > 0) { glm::vec2 minCoord = pts[0]; glm::vec2 maxCoord = pts[0]; for (unsigned i = 1; i < pts.size(); ++i) { if (pts[i].x < minCoord.x) { minCoord.x = pts[i].x; } if (pts[i].x > maxCoord.x) { maxCoord.x = pts[i].x; } if (pts[i].y < minCoord.y) { minCoord.y = pts[i].y; } if (pts[i].y > maxCoord.y) { maxCoord.y = pts[i].y; } } vector<unsigned int> triIndexes; triangulatePolygon(triIndexes, pts, holeIndexes); for (unsigned i = 0; i < pts.size(); ++i) { glm::vec2 texCoord = calcFillTexCoord(pts[i], minCoord, maxCoord); pVertexData->appendPos(pts[i], texCoord, color); } for (unsigned i = 0; i < triIndexes.size(); i+=3) { pVertexData->appendTriIndexes(triIndexes[i], triIndexes[i+1], triIndexes[i+2]); } } }
void VectorNode::calcPolyLine(const vector<glm::vec2>& origPts, const vector<float>& origTexCoords, bool bIsClosed, LineJoin lineJoin, const VertexDataPtr& pVertexData, Pixel32 color) { vector<glm::vec2> pts; pts.reserve(origPts.size()); vector<float> texCoords; texCoords.reserve(origPts.size()); pts.push_back(origPts[0]); texCoords.push_back(origTexCoords[0]); for (unsigned i = 1; i < origPts.size(); ++i) { if (glm::distance2(origPts[i], origPts[i-1]) > 0.1) { pts.push_back(origPts[i]); texCoords.push_back(origTexCoords[i]); } } if (bIsClosed) { texCoords.push_back(origTexCoords[origTexCoords.size()-1]); } int numPts = pts.size(); // Create array of wide lines. vector<WideLine> lines; lines.reserve(numPts-1); for (int i = 0; i < numPts-1; ++i) { lines.push_back(WideLine(pts[i], pts[i+1], m_StrokeWidth)); } if (bIsClosed) { lines.push_back(WideLine(pts[numPts-1], pts[0], m_StrokeWidth)); } // First points if (bIsClosed) { WideLine lastLine = lines[lines.size()-1]; glm::vec2 pli = getLineLineIntersection(lastLine.pl0, lastLine.dir, lines[0].pl0, lines[0].dir); glm::vec2 pri = getLineLineIntersection(lastLine.pr0, lastLine.dir, lines[0].pr0, lines[0].dir); Triangle tri(lastLine.pl1, lines[0].pl0, pri); if (tri.isClockwise()) { if (!LineSegment(lastLine.pr0, lastLine.pr1).isPointOver(pri) && !LineSegment(lines[0].pr0, lines[0].pr1).isPointOver(pri)) { pri = lines[0].pr1; } } else { if (!LineSegment(lastLine.pl0, lastLine.pl1).isPointOver(pli) && !LineSegment(lines[0].pl0, lines[0].pl1).isPointOver(pli)) { pli = lines[0].pl1; } } float curTC = texCoords[0]; switch (lineJoin) { case LJ_MITER: pVertexData->appendPos(pli, glm::vec2(curTC,1), color); pVertexData->appendPos(pri, glm::vec2(curTC,0), color); break; case LJ_BEVEL: { if (tri.isClockwise()) { pVertexData->appendPos(lines[0].pl0, glm::vec2(curTC,1), color); pVertexData->appendPos(pri, glm::vec2(curTC,0), color); } else { pVertexData->appendPos(pli, glm::vec2(curTC,1), color); pVertexData->appendPos(lines[0].pr0, glm::vec2(curTC,0), color); } } break; default: AVG_ASSERT(false); break; } } else { pVertexData->appendPos(lines[0].pl0, glm::vec2(texCoords[0],1), color); pVertexData->appendPos(lines[0].pr0, glm::vec2(texCoords[0],0), color); } // All complete line segments unsigned numNormalSegments; if (bIsClosed) { numNormalSegments = pts.size(); } else { numNormalSegments = pts.size()-2; } for (unsigned i = 0; i < numNormalSegments; ++i) { const WideLine* pLine1 = &(lines[i]); const WideLine* pLine2; if (i == pts.size()-1) { pLine2 = &(lines[0]); } else { pLine2 = &(lines[i+1]); } glm::vec2 pli = getLineLineIntersection(pLine1->pl0, pLine1->dir, pLine2->pl0, pLine2->dir); glm::vec2 pri = getLineLineIntersection(pLine1->pr0, pLine1->dir, pLine2->pr0, pLine2->dir); Triangle tri(pLine1->pl1, pLine2->pl0, pri); if (tri.isClockwise()) { if (!LineSegment(pLine1->pr0, pLine1->pr1).isPointOver(pri) && !LineSegment(pLine2->pr0, pLine2->pr1).isPointOver(pri)) { pri = pLine2->pr1; } } else { if (!LineSegment(pLine1->pl0, pLine1->pl1).isPointOver(pli) && !LineSegment(pLine2->pl0, pLine2->pl1).isPointOver(pli)) { pli = pLine2->pl1; } } int curVertex = pVertexData->getNumVerts(); float curTC = texCoords[i+1]; switch (lineJoin) { case LJ_MITER: pVertexData->appendPos(pli, glm::vec2(curTC,1), color); pVertexData->appendPos(pri, glm::vec2(curTC,0), color); pVertexData->appendQuadIndexes( curVertex-1, curVertex-2, curVertex+1, curVertex); break; case LJ_BEVEL: { float TC0; float TC1; if (tri.isClockwise()) { calcBevelTC(*pLine1, *pLine2, true, texCoords, i+1, TC0, TC1); pVertexData->appendPos(pLine1->pl1, glm::vec2(TC0,1), color); pVertexData->appendPos(pLine2->pl0, glm::vec2(TC1,1), color); pVertexData->appendPos(pri, glm::vec2(curTC,0), color); pVertexData->appendQuadIndexes( curVertex-1, curVertex-2, curVertex+2, curVertex); pVertexData->appendTriIndexes( curVertex, curVertex+1, curVertex+2); } else { calcBevelTC(*pLine1, *pLine2, false, texCoords, i+1, TC0, TC1); pVertexData->appendPos(pLine1->pr1, glm::vec2(TC0,0), color); pVertexData->appendPos(pli, glm::vec2(curTC,1), color); pVertexData->appendPos(pLine2->pr0, glm::vec2(TC1,0), color); pVertexData->appendQuadIndexes( curVertex-2, curVertex-1, curVertex+1, curVertex); pVertexData->appendTriIndexes( curVertex, curVertex+1, curVertex+2); } } break; default: AVG_ASSERT(false); } } // Last segment (PolyLine only) if (!bIsClosed) { int curVertex = pVertexData->getNumVerts(); float curTC = texCoords[numPts-1]; pVertexData->appendPos(lines[numPts-2].pl1, glm::vec2(curTC,1), color); pVertexData->appendPos(lines[numPts-2].pr1, glm::vec2(curTC,0), color); pVertexData->appendQuadIndexes(curVertex-1, curVertex-2, curVertex+1, curVertex); } }