shithub: libgraphics

Download patch

ref: e2e203e6fa64a9e57c8d4ba4cea4deec89d8f0c1
parent: d3516b11559657935d70829c672f29393e857b8e
author: rodri <rgl@antares-labs.eu>
date: Tue May 21 12:59:33 EDT 2024

fix line rasterization.

--- a/clip.c
+++ b/clip.c
@@ -53,6 +53,21 @@
 	p->n = 0;
 }
 
+static void
+fprintpoly(int fd, Polygon *p)
+{
+	int i;
+
+	for(i = 0; i < p->n; i++)
+		fprint(fd, "%d/%lud p %V\n", i, p->n, p->v[i].p);
+}
+
+static int
+eqpt3(Point3 a, Point3 b)
+{
+	return vec3len(subpt3(a, b)) < 1e-6;
+}
+
 /*
  * references:
  * 	- James F. Blinn, Martin E. Newell, “Clipping Using Homogeneous Coordinates”,
@@ -76,9 +91,9 @@
 	double d0, d1, perc;
 	Polygon Vin, Vout;
 	Vertex *v0, *v1, v;	/* edge verts and new vertex (line-plane intersection) */
-	int i, j, nt;
+	int i, j, np;
 
-	nt = 0;
+	np = 0;
 	memset(&Vin, 0, sizeof Vin);
 	memset(&Vout, 0, sizeof Vout);
 	for(i = 0; i < p[0].type+1; i++)
@@ -119,23 +134,23 @@
 		cleanpoly(&Vout);
 	else switch(p[0].type){
 	case PLine:
-		/* TODO fix line clipping (they disappear instead, why?) */
 		p[0].v[0] = dupvertex(&Vout.v[0]);
-		p[0].v[1] = dupvertex(&Vout.v[1]);
+		p[0].v[1] = eqpt3(Vout.v[0].p, Vout.v[1].p)? dupvertex(&Vout.v[2]): dupvertex(&Vout.v[1]);
 		cleanpoly(&Vout);
+		np = 1;
 		break;
 	case PTriangle:
 		/* triangulate */
-		for(i = 0; i < Vout.n-2; i++, nt++){
+		for(i = 0; i < Vout.n-2; i++, np++){
 			/*
 			 * when performing fan triangulation, indices 0 and 2
 			 * are referenced on every triangle, so duplicate them
 			 * to avoid complications during rasterization.
 			 */
-			memmove(&p[nt], &p[0], sizeof *p);
-			p[nt].v[0] = i < Vout.n-2-1? dupvertex(&Vout.v[0]): Vout.v[0];
-			p[nt].v[1] = Vout.v[i+1];
-			p[nt].v[2] = i < Vout.n-2-1? dupvertex(&Vout.v[i+2]): Vout.v[i+2];
+			memmove(&p[np], &p[0], sizeof *p);
+			p[np].v[0] = i < Vout.n-2-1? dupvertex(&Vout.v[0]): Vout.v[0];
+			p[np].v[1] = Vout.v[i+1];
+			p[np].v[2] = i < Vout.n-2-1? dupvertex(&Vout.v[i+2]): Vout.v[i+2];
 		}
 		break;
 	}
@@ -142,7 +157,7 @@
 	free(Vout.v);
 	free(Vin.v);
 
-	return nt;
+	return np;
 }
 
 static int
--- a/render.c
+++ b/render.c
@@ -119,11 +119,12 @@
 			dplen = hypot(dp.x, dp.y);
 			perc = dplen == 0? 0: hypot(Δp.x, Δp.y)/dplen;
 
-			/* TODO it seems depth testing messes with the output. find out why */
+			if(steep) swapi(&p.x, &p.y);
+
 			z = flerp(prim.v[0].p.z, prim.v[1].p.z, perc);
 			depth = fclamp(z, 0, 1);
-			if(depth <= params->fb->zb[p.x + p.y*Dx(params->fb->r)])
-				continue;
+			if(!ptinrect(p, params->fb->r) || depth <= params->fb->zb[p.x + p.y*Dx(params->fb->r)])
+				goto discard;
 			params->fb->zb[p.x + p.y*Dx(params->fb->r)] = depth;
 
 			/* interpolate z⁻¹ and get actual z */
@@ -134,8 +135,6 @@
 			perc *= prim.v[0].p.w * z;
 			lerpvertex(&fsp.v, &prim.v[0], &prim.v[1], perc);
 
-			if(steep) swapi(&p.x, &p.y);
-
 			fsp.p = p;
 			c = params->fshader(&fsp);
 			memfillcolor(params->frag, col2ul(c));
@@ -142,7 +141,7 @@
 
 			pixel(params->fb->cb, p, params->frag);
 			delvattrs(&fsp.v);
-
+discard:
 			if(steep) swapi(&p.x, &p.y);
 
 			e += Δe;
--- a/xform.c
+++ b/xform.c
@@ -145,13 +145,12 @@
 	double cotan;
 
 	cotan = 1/tan(fovy/2);
-	identity3(m);
+	memset(m, 0, 4*4*sizeof(double));
 	m[0][0] =  cotan/a;
 	m[1][1] =  cotan;
 	m[2][2] =  (f+n)/(f-n);
 	m[2][3] =  2*f*n/(f-n);
 	m[3][2] = -1;
-	m[3][3] = 0;
 }
 
 void