graphics: fix for anti-parallel line segments (#1894)

Handle the case when a line doubles back on itself, eg

  love.graphics.setLineJoin("bevel")
  love.graphics.line({
    180, 400,
    200, 400,
    100, 400
  })
This commit is contained in:
scurest
2023-02-21 19:00:29 -06:00
committed by Sasha Szpakowski
parent a71cfdcb50
commit 106daedf75
+29 -4
View File
@@ -188,11 +188,26 @@ void MiterJoinPolyline::renderEdge(std::vector<Vector2> &anchors, std::vector<Ve
anchors.push_back(pointA);
float det = Vector2::cross(segment, newSegment);
if (fabs(det) / (segmentLength * newSegmentLength) < LINES_PARALLEL_EPS && Vector2::dot(segment, newSegment) > 0)
if (fabs(det) / (segmentLength * newSegmentLength) < LINES_PARALLEL_EPS)
{
// lines parallel, compute as u1 = q + ns * w/2, u2 = q - ns * w/2
normals.push_back(segmentNormal);
normals.push_back(-segmentNormal);
if (Vector2::dot(segment, newSegment) < 0)
{
// line reverses direction; because the normal flips, the
// triangle strip would twist here, so insert a zero-size
// quad to contain the twist
// ____.___.____
// | |\ /| |
// p q X q r
// |____|/ \|____|
anchors.push_back(pointA);
anchors.push_back(pointA);
normals.push_back(-segmentNormal);
normals.push_back(segmentNormal);
}
}
else
{
@@ -233,14 +248,24 @@ void BevelJoinPolyline::renderEdge(std::vector<Vector2> &anchors, std::vector<Ve
float newSegmentLength = newSegment.getLength();
float det = Vector2::cross(segment, newSegment);
if (fabs(det) / (segmentLength * newSegmentLength) < LINES_PARALLEL_EPS && Vector2::dot(segment, newSegment) > 0)
if (fabs(det) / (segmentLength * newSegmentLength) < LINES_PARALLEL_EPS)
{
// lines parallel, compute as u1 = q + ns * w/2, u2 = q - ns * w/2
Vector2 newSegmentNormal = newSegment.getNormal(halfWidth / newSegmentLength);
anchors.push_back(pointA);
anchors.push_back(pointA);
normals.push_back(newSegmentNormal);
normals.push_back(-newSegmentNormal);
normals.push_back(segmentNormal);
normals.push_back(-segmentNormal);
if (Vector2::dot(segment, newSegment) < 0)
{
// line reverses direction; same as for miter
anchors.push_back(pointA);
anchors.push_back(pointA);
normals.push_back(-segmentNormal);
normals.push_back(segmentNormal);
}
segment = newSegment;
segmentLength = newSegmentLength;
segmentNormal = newSegmentNormal;