diff options
-rw-r--r-- | clip.c | 34 | ||||
-rw-r--r-- | internal.h | 3 | ||||
-rw-r--r-- | render.c | 6 | ||||
-rw-r--r-- | vertex.c | 10 |
4 files changed, 46 insertions, 7 deletions
@@ -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){ @@ -45,6 +45,7 @@ void rmfbctl(Framebufctl*); /* vertex */ Vertex dupvertex(Vertex*); +void swapvertex(Vertex*, Vertex*); void lerpvertex(Vertex*, Vertex*, Vertex*, double); void berpvertex(Vertex*, Vertex*, Vertex*, Vertex*, Point3); void delvattrs(Vertex*); @@ -52,7 +53,7 @@ void fprintvattrs(int, Vertex*); /* clip */ int clipprimitive(Primitive*, Primitive*); -int rectclipline(Rectangle, Point*, Point*); +int rectclipline(Rectangle, Point*, Point*, Vertex*, Vertex*); /* util */ int min(int, int); @@ -128,7 +128,7 @@ rasterize(Rastertask *task) p0 = Pt(prim.v[0].p.x, prim.v[0].p.y); p1 = Pt(prim.v[1].p.x, prim.v[1].p.y); /* clip it against our wr */ - if(rectclipline(task->wr, &p0, &p1) < 0) + if(rectclipline(task->wr, &p0, &p1, &prim.v[0], &prim.v[1]) < 0) break; /* transpose the points */ @@ -140,8 +140,8 @@ rasterize(Rastertask *task) /* make them left-to-right */ if(p0.x > p1.x){ - swapi(&p0.x, &p1.x); - swapi(&p0.y, &p1.y); + swappt(&p0, &p1); + swapvertex(&prim.v[0], &prim.v[1]); } dp = subpt(p1, p0); @@ -43,6 +43,16 @@ dupvertex(Vertex *v) return nv; } +void +swapvertex(Vertex *a, Vertex *b) +{ + Vertex t; + + t = *a; + *a = *b; + *b = t; +} + /* * linear attribute interpolation */ |