summaryrefslogtreecommitdiff
path: root/clip.c
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2024-08-02 17:57:42 +0000
committerrodri <rgl@antares-labs.eu>2024-08-02 17:57:42 +0000
commit50f15bac90638da401d27229969dc502c75d1320 (patch)
tree2f8bf3b8df50292938d5bca01eb3c0ef3ff1f12f /clip.c
parent3bf0f4fdcf9e1a61881c20ee8162924f952ba8e0 (diff)
downloadlibgraphics-50f15bac90638da401d27229969dc502c75d1320.tar.gz
libgraphics-50f15bac90638da401d27229969dc502c75d1320.tar.bz2
libgraphics-50f15bac90638da401d27229969dc502c75d1320.zip
fix line interpolation during rasterization.
vertex attributes were not being updated after clipping with their corresponding work rectangles, nor when reordering the points before rasterization, which caused serious artifacts.
Diffstat (limited to 'clip.c')
-rw-r--r--clip.c34
1 files changed, 31 insertions, 3 deletions
diff --git a/clip.c b/clip.c
index a7750cf..9988ce1 100644
--- a/clip.c
+++ b/clip.c
@@ -193,11 +193,37 @@ outcode(Point p, Rectangle r)
return code;
}
+/* lerp vertex attributes to match the new positions */
+void
+adjustverts(Point *p0, Point *p1, Vertex *v0, Vertex *v1)
+{
+ Vertex v[2];
+ Point3 dp;
+ Point Δp;
+ double len, perc;
+
+ dp = subpt3(v1->p, v0->p);
+ len = hypot(dp.x, dp.y);
+
+ Δp = subpt(Pt(v0->p.x, v0->p.y), *p0);
+ perc = len == 0? 0: hypot(Δp.x, Δp.y)/len;
+ lerpvertex(&v[0], v0, v1, perc);
+
+ Δp = subpt(Pt(v0->p.x, v0->p.y), *p1);
+ perc = len == 0? 0: hypot(Δp.x, Δp.y)/len;
+ lerpvertex(&v[1], v0, v1, perc);
+
+ delvattrs(v0);
+ delvattrs(v1);
+ *v0 = dupvertex(&v[0]);
+ *v1 = dupvertex(&v[1]);
+}
+
/*
* Cohen-Sutherland rectangle-line clipping
*/
int
-rectclipline(Rectangle r, Point *p0, Point *p1)
+rectclipline(Rectangle r, Point *p0, Point *p1, Vertex *v0, Vertex *v1)
{
int code0, code1;
int Δx, Δy;
@@ -211,14 +237,16 @@ rectclipline(Rectangle r, Point *p0, Point *p1)
code0 = outcode(*p0, r);
code1 = outcode(*p1, r);
- if(lineisinside(code0, code1))
+ if(lineisinside(code0, code1)){
+ adjustverts(p0, p1, v0, v1);
return 0;
- else if(lineisoutside(code0, code1))
+ }else if(lineisoutside(code0, code1))
return -1;
if(ptisinside(code0)){
swappt(p0, p1);
swapi(&code0, &code1);
+ swapvertex(v0, v1);
}
if(code0 & CLIPL){