void VertexData::appendVertexData(const VertexDataPtr& pVertexes) { int oldNumVerts = m_NumVerts; int oldNumIndexes = m_NumIndexes; m_NumVerts += pVertexes->getNumVerts(); m_NumIndexes += pVertexes->getNumIndexes(); if (m_NumVerts > m_ReserveVerts || m_NumIndexes > m_ReserveIndexes) { grow(); } memcpy(&(m_pVertexData[oldNumVerts]), pVertexes->m_pVertexData, pVertexes->getNumVerts()*sizeof(Vertex)); int numIndexes = pVertexes->getNumIndexes(); for (int i=0; i<numIndexes; ++i) { m_pIndexData[oldNumIndexes+i] = pVertexes->m_pIndexData[i] + oldNumVerts; } m_bDataChanged = true; }
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); } }