Implement line clipping for `TextureProgress` to avoid bad rendering due to imprecise UV mapping

Original code used a quick aproximation for simulating the
correspondent texel in the `TextureProgress` texture as radial
progress indicator. This lead to visualization errors. Changed it for
a Liang-Barsky line clipping algorithm stripped to its minimum for
this specific use case.

Fix #17364.

(cherry picked from commit 7991bd168d)
This commit is contained in:
robfram 2018-03-10 20:51:42 +01:00 committed by Hein-Pieter van Braam
parent c39e32ae60
commit b855bc44ae
1 changed files with 39 additions and 16 deletions

View File

@ -117,22 +117,45 @@ Point2 TextureProgress::unit_val_to_uv(float val) {
Point2 p = get_relative_center(); Point2 p = get_relative_center();
if (val < 0.125) // Minimal version of Liang-Barsky clipping algorithm
return Point2(p.x + (1 - p.x) * val * 8, 0); float angle = (val * Math_TAU) - Math_PI * 0.5;
if (val < 0.25) Point2 dir = Vector2(Math::cos(angle), Math::sin(angle));
return Point2(1, p.y * (val - 0.125) * 8); float t1 = 1.0;
if (val < 0.375) float cp;
return Point2(1, p.y + (1 - p.y) * (val - 0.25) * 8); float cq;
if (val < 0.5) float cr;
return Point2(1 - (1 - p.x) * (val - 0.375) * 8, 1); float edgeLeft = 0.0;
if (val < 0.625) float edgeRight = 1.0;
return Point2(p.x * (1 - (val - 0.5) * 8), 1); float edgeBottom = 0.0;
if (val < 0.75) float edgeTop = 1.0;
return Point2(0, 1 - ((1 - p.y) * (val - 0.625) * 8));
if (val < 0.875) for (int edge = 0; edge < 4; edge++) {
return Point2(0, p.y - p.y * (val - 0.75) * 8); if (edge == 0) {
else if (dir.x > 0)
return Point2(p.x * (val - 0.875) * 8, 0); continue;
cp = -dir.x;
cq = -(edgeLeft - p.x);
} else if (edge == 1) {
if (dir.x < 0)
continue;
cp = dir.x;
cq = (edgeRight - p.x);
} else if (edge == 2) {
if (dir.y > 0)
continue;
cp = -dir.y;
cq = -(edgeBottom - p.y);
} else if (edge == 3) {
if (dir.y < 0)
continue;
cp = dir.y;
cq = (edgeTop - p.y);
}
cr = cq / cp;
if (cr >= 0 && cr < t1)
t1 = cr;
}
return (p + t1 * dir);
} }
Point2 TextureProgress::get_relative_center() { Point2 TextureProgress::get_relative_center() {