shithub: libgraphics

Download patch

ref: dc597a2c65278119b7d11f83218b860c0c5da051
parent: 5fa75a6d4b03c676112ca04cf5ff3f3ccd2f0fee
author: rodri <rgl@antares-labs.eu>
date: Tue Jun 4 14:11:11 EDT 2024

add a tangent parameter for normal mapping, and a world2model xform.

--- a/graphics.h
+++ b/graphics.h
@@ -87,6 +87,7 @@
 	Color c;		/* shading color */
 	Point2 uv;		/* texture coordinate */
 	Material *mtl;
+	Point3 tangent;
 
 	/* TODO it'd be neat to use a dynamic hash table instead */
 	Vertexattr *attrs;	/* attributes (aka varyings) */
@@ -116,6 +117,7 @@
 	int type;
 	Vertex v[3];
 	Material *mtl;
+	Point3 tangent;		/* used for normal mapping */
 };
 
 struct Model
@@ -123,7 +125,6 @@
 	Primitive *prims;
 	ulong nprims;
 	Memimage *tex;		/* texture map */
-	Memimage *nor;		/* normals map */
 	Material *materials;
 	ulong nmaterials;
 };
@@ -290,6 +291,7 @@
 Point3 viewport2vcs(Camera*, Point3);
 Point3 vcs2world(Camera*, Point3);
 Point3 viewport2world(Camera*, Point3);
+Point3 world2model(Entity*, Point3);
 void perspective(Matrix3, double, double, double, double);
 void orthographic(Matrix3, double, double, double, double, double, double);
 
--- a/render.c
+++ b/render.c
@@ -351,10 +351,6 @@
 					p[np].v[0].p = clip2ndc(p[np].v[0].p);
 					p[np].v[1].p = clip2ndc(p[np].v[1].p);
 
-					/* culling */
-//					if(isfacingback(p[np]))
-//						goto skiptri2;
-
 					p[np].v[0].p = ndc2viewport(params->fb, p[np].v[0].p);
 					p[np].v[1].p = ndc2viewport(params->fb, p[np].v[1].p);
 
@@ -375,7 +371,6 @@
 							task->p.v[1] = dupvertex(&p[np].v[1]);
 							sendp(taskchans[i], task);
 						}
-//skiptri2:
 					delvattrs(&p[np].v[0]);
 					delvattrs(&p[np].v[1]);
 				}
@@ -386,6 +381,7 @@
 					p[0].v[i].mtl = p->mtl;
 					p[0].v[i].attrs = nil;
 					p[0].v[i].nattrs = 0;
+					p[0].v[i].tangent = p->tangent;
 
 					vsp.v = &p[0].v[i];
 					vsp.idx = i;
--- a/scene.c
+++ b/scene.c
@@ -277,6 +277,23 @@
 								p->v[idx].uv = Pt2(v->u, v->v, 1);
 							}
 						}
+						if(p->v[0].uv.w != 0){
+							Point3 e0, e1;
+							Point2 Δuv0, Δuv1;
+							double det;
+
+							e0 = subpt3(p->v[1].p, p->v[0].p);
+							e1 = subpt3(p->v[2].p, p->v[0].p);
+							Δuv0 = subpt2(p->v[1].uv, p->v[0].uv);
+							Δuv1 = subpt2(p->v[2].uv, p->v[0].uv);
+
+							det = Δuv0.x * Δuv1.y - Δuv1.x * Δuv0.y;
+							det = det == 0? 0: 1.0/det;
+							p->tangent.x = det*(Δuv1.y * e0.x - Δuv0.y * e1.x);
+							p->tangent.y = det*(Δuv1.y * e0.y - Δuv0.y * e1.y);
+							p->tangent.z = det*(Δuv1.y * e0.z - Δuv0.y * e1.z);
+							p->tangent = normvec3(p->tangent);
+						}
 						if(neednormal){
 							/* TODO build a list of per-vertex normals earlier */
 							n = normvec3(crossvec3(subpt3(p->v[1].p, p->v[0].p), subpt3(p->v[2].p, p->v[0].p)));
@@ -316,11 +333,12 @@
 		return;
 	if(m->tex != nil)
 		freememimage(m->tex);
-	if(m->nor != nil)
-		freememimage(m->nor);
 	if(m->nmaterials > 0){
-		while(m->nmaterials--)
+		while(m->nmaterials--){
+			freememimage(m->materials[m->nmaterials].diffusemap);
+			freememimage(m->materials[m->nmaterials].normalmap);
 			free(m->materials[m->nmaterials].name);
+		}
 		free(m->materials);
 	}
 	if(m->nprims > 0)
--- a/xform.c
+++ b/xform.c
@@ -139,6 +139,12 @@
 	return vcs2world(c, viewport2vcs(c, p));
 }
 
+Point3
+world2model(Entity *e, Point3 p)
+{
+	return rframexform3(p, *e);
+}
+
 void
 perspective(Matrix3 m, double fovy, double a, double n, double f)
 {