shithub: tinyrend

Download patch

ref: dc4da2505ec30449b9393182a3cb76937992dd3c
parent: 873c10820c62e5f2d206131a8d6f52195a596aa8
author: rodri <[email protected]>
date: Sun Nov 19 07:25:44 EST 2023

add the option to visualize normals.

--- a/main.c
+++ b/main.c
@@ -34,7 +34,7 @@
 };
 
 
-Memimage *fb, *zfb, *curfb;
+Memimage *screenfb, *fb, *zfb, *nfb, *curfb;
 double *zbuf;
 Lock zbuflk;
 Memimage *red, *green, *blue;
@@ -44,6 +44,7 @@
 int nprocs;
 int rendering;
 int flag2;
+int shownormals;
 
 char winspec[32];
 Point3 camera = {0,0,3,1};
@@ -332,7 +333,7 @@
 }
 
 void
-filltriangle2(Memimage *dst, Triangle3 st, Triangle2 tt, double intensity, Memimage *frag)
+filltriangle2(Memimage *dst, Triangle3 st, Triangle3 nt, Triangle2 tt, double intensity, Memimage *frag)
 {
 	Rectangle bbox;
 	Point p, tp;
@@ -453,14 +454,15 @@
 {
 	SUparams *params;
 	Sparams sp;
-	OBJVertex *verts, *tverts;		/* geometric and texture vertices */
+	OBJVertex *verts, *tverts, *nverts;	/* geometric, texture and normals vertices */
 	OBJIndexArray *idxtab;
 	OBJElem **ep;
-	Triangle3 t, st;			/* world- and screen-space triangles */
+	Triangle3 t, st, nt;			/* world-, screen-space and normals triangles */
 	Triangle2 tt;				/* texture triangle */
 	Point3 n;				/* surface normal */
 	static Point3 light = {0,0,-1,0};	/* global light field */
 	double intensity;
+	Point3 np0, np1;
 
 	params = arg;
 	sp.frag = rgb(DBlack);
@@ -469,6 +471,7 @@
 
 	verts = model->vertdata[OBJVGeometric].verts;
 	tverts = model->vertdata[OBJVTexture].verts;
+	nverts = model->vertdata[OBJVNormal].verts;
 
 	for(ep = params->b; ep != params->e; ep++){
 		idxtab = &(*ep)->indextab[OBJVGeometric];
@@ -490,6 +493,18 @@
 		if(intensity <= 0)
 			continue;
 
+		np0 = centroid3(st);
+		np1 = addpt3(np0, mulpt3(n, 10));
+		bresenham(nfb, Pt(np0.x,np0.y), Pt(np1.x,np1.y), green);
+
+		idxtab = &(*ep)->indextab[OBJVNormal];
+		if(modeltex != nil && idxtab->nindex == 3){
+			nt.p0 = Vec3(nverts[idxtab->indices[0]].i, nverts[idxtab->indices[0]].j, nverts[idxtab->indices[0]].k);
+			nt.p1 = Vec3(nverts[idxtab->indices[1]].i, nverts[idxtab->indices[1]].j, nverts[idxtab->indices[1]].k);
+			nt.p2 = Vec3(nverts[idxtab->indices[2]].i, nverts[idxtab->indices[2]].j, nverts[idxtab->indices[2]].k);
+		}else
+			memset(&nt, 0, sizeof nt);
+
 		idxtab = &(*ep)->indextab[OBJVTexture];
 		if(modeltex != nil && idxtab->nindex == 3){
 			tt.p0 = Pt2(tverts[idxtab->indices[0]].u, tverts[idxtab->indices[0]].v, 1);
@@ -498,7 +513,7 @@
 		}else
 			memset(&tt, 0, sizeof tt);
 
-		filltriangle2(params->dst, st, tt, intensity, sp.frag);
+		filltriangle2(params->dst, st, nt, tt, intensity, sp.frag);
 	}
 
 	freememimage(sp.frag);
@@ -742,8 +757,11 @@
 redraw(void)
 {
 	lockdisplay(display);
-	draw(screen, screen->r, display->black, nil, ZP);
-	loadimage(screen, rectaddpt(curfb->r, screen->r.min), byteaddr(curfb, curfb->r.min), bytesperline(curfb->r, curfb->depth)*Dy(curfb->r));
+	memfillcolor(screenfb, DBlack);
+	memimagedraw(screenfb, screenfb->r, curfb, ZP, nil, ZP, SoverD);
+	if(shownormals)
+		memimagedraw(screenfb, screenfb->r, nfb, ZP, nil, ZP, SoverD);
+	loadimage(screen, rectaddpt(screenfb->r, screen->r.min), byteaddr(screenfb, screenfb->r.min), bytesperline(screenfb->r, screenfb->depth)*Dy(screenfb->r));
 	flushimage(display, 1);
 	unlockdisplay(display);
 }
@@ -794,10 +812,15 @@
 {
 	enum {
 		TOGGLEZBUF,
+		TOGGLENORM,
 	};
 
-	if(idx == TOGGLEZBUF)
+	switch(idx){
+	case TOGGLEZBUF:
 		return curfb == zfb? "hide z-buffer": "show z-buffer";
+	case TOGGLENORM:
+		return shownormals? "hide normals": "show normals";
+	}
 	return nil;
 }
 
@@ -806,6 +829,7 @@
 {
 	enum {
 		TOGGLEZBUF,
+		TOGGLENORM,
 	};
 	static Menu menu = { .gen = genrmbmenuitem };
 
@@ -813,6 +837,9 @@
 	case TOGGLEZBUF:
 		curfb = curfb == fb? zfb: fb;
 		break;
+	case TOGGLENORM:
+		shownormals ^= 1;
+		break;
 	}
 	nbsendp(drawc, nil);
 }
@@ -904,11 +931,13 @@
 	if((kc = initkeyboard(nil)) == nil)
 		sysfatal("initkeyboard: %r");
 
-	fb = eallocmemimage(rectsubpt(screen->r, screen->r.min), screen->chan);
+	screenfb = eallocmemimage(rectsubpt(screen->r, screen->r.min), screen->chan);
+	fb = eallocmemimage(screenfb->r, RGBA32);
 	zbuf = emalloc(Dx(fb->r)*Dy(fb->r)*sizeof(double));
 	memsetd(zbuf, Inf(-1), Dx(fb->r)*Dy(fb->r));
 	zfb = eallocmemimage(fb->r, fb->chan);
 	curfb = fb;
+	nfb = eallocmemimage(fb->r, fb->chan);
 	red = rgb(DRed);
 	green = rgb(DGreen);
 	blue = rgb(DBlue);