Browse Source

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
  })
scurest 2 years ago
parent
commit
106daedf75
1 changed files with 29 additions and 4 deletions
  1. 29 4
      src/modules/graphics/Polyline.cpp

+ 29 - 4
src/modules/graphics/Polyline.cpp

@@ -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;