shithub: libgraphics

Download patch

ref: d4991f0af282bbc996474af2caf59b8fd7dc35f3
parent: 79ad08a0818642903d8fd46492f498acff3cab27
author: rodri <rgl@antares-labs.eu>
date: Thu Jul 3 11:46:13 EDT 2025

implement naive model compaction routine

--- a/graphics.h
+++ b/graphics.h
@@ -457,13 +457,6 @@
 int exportmodel(char*, Model*);
 
 /* scene */
-Vertex mkvert(void);
-Primitive mkprim(int);
-Material *newmaterial(char*);
-void delmaterial(Material*);
-Model *newmodel(void);
-Model *dupmodel(Model*);
-void delmodel(Model*);
 LightSource *newpointlight(Point3, Color);
 LightSource *newdireclight(Point3, Point3, Color);
 LightSource *newspotlight(Point3, Point3, Color, double, double);
@@ -477,6 +470,16 @@
 void delscene(Scene*);
 void clearscene(Scene*);
 
+/* model */
+Vertex mkvert(void);
+Primitive mkprim(int);
+Material *newmaterial(char*);
+void delmaterial(Material*);
+Model *newmodel(void);
+Model *dupmodel(Model*);
+void delmodel(Model*);
+void compactmodel(Model*);
+
 /* texture */
 Texture *alloctexture(int, Memimage*);
 Texture *duptexture(Texture*);
@@ -505,7 +508,7 @@
 
 /* itemarray */
 ItemArray *mkitemarray(usize);
-usize itemarrayadd(ItemArray*, void*, int);
+usize itemarrayadd(ItemArray*, void*);
 void *itemarrayget(ItemArray*, usize);
 usize copyitemarray(ItemArray*, ItemArray*);
 ItemArray *dupitemarray(ItemArray*);
--- a/itemarray.c
+++ b/itemarray.c
@@ -20,17 +20,10 @@
 }
 
 usize
-itemarrayadd(ItemArray *a, void *i, int dedup)
+itemarrayadd(ItemArray *a, void *i)
 {
 	char *p;
 	usize idx;
-
-	if(dedup){
-		p = a->items;
-		for(idx = 0; idx < a->nitems; idx++)
-			if(memcmp(i, &p[idx*a->itemsize], a->itemsize) == 0)
-				return idx;
-	}
 
 	idx = a->nitems;
 	a->items = _erealloc(a->items, ++a->nitems * a->itemsize);
--- a/marshal.c
+++ b/marshal.c
@@ -335,7 +335,7 @@
 			p.y = strtod(f[2], nil);
 			p.z = strtod(f[3], nil);
 			p.w = nf == 5? strtod(f[4], nil): 1;
-			itemarrayadd(pa, &p, 0);
+			itemarrayadd(pa, &p);
 		}else if(strcmp(f[0], "n") == 0){
 			if(nf != 4){
 				error(&curline, "syntax error");
@@ -344,7 +344,7 @@
 			n.x = strtod(f[1], nil);
 			n.y = strtod(f[2], nil);
 			n.z = strtod(f[3], nil);
-			itemarrayadd(na, &n, 0);
+			itemarrayadd(na, &n);
 		}else if(strcmp(f[0], "t") == 0){
 			if(nf != 3){
 				error(&curline, "syntax error");
@@ -352,7 +352,7 @@
 			}
 			t.x = strtod(f[1], nil);
 			t.y = strtod(f[2], nil);
-			itemarrayadd(ta, &t, 0);
+			itemarrayadd(ta, &t);
 		}else if(strcmp(f[0], "c") == 0){
 			if(nf != 4 && nf != 5){
 				error(&curline, "syntax error");
@@ -362,7 +362,7 @@
 			c.g = strtod(f[2], nil);
 			c.b = strtod(f[3], nil);
 			c.a = nf == 5? strtod(f[4], nil): 1;
-			itemarrayadd(ca, &c, 0);
+			itemarrayadd(ca, &c);
 		}else if(strcmp(f[0], "T") == 0){
 			if(nf != 4){
 				error(&curline, "syntax error");
@@ -371,7 +371,7 @@
 			T.x = strtod(f[1], nil);
 			T.y = strtod(f[2], nil);
 			T.z = strtod(f[3], nil);
-			itemarrayadd(Ta, &T, 0);
+			itemarrayadd(Ta, &T);
 		}else if(strcmp(f[0], "v") == 0){
 			if(nf != 5){
 				error(&curline, "syntax error");
@@ -421,7 +421,7 @@
 				v.c = idx;
 			}
 
-			itemarrayadd(va, &v, 0);
+			itemarrayadd(va, &v);
 		}else if(strcmp(f[0], "P") == 0){
 			if(nf < 3 || nf > 7){
 				error(&curline, "syntax error");
@@ -535,7 +535,7 @@
 				goto getout;
 			}
 
-			itemarrayadd(Pa, &P, 0);
+			itemarrayadd(Pa, &P);
 		}else if(strcmp(f[0], "mtl") == 0){
 			if(nf != 3 || strcmp(f[2], "{") != 0){
 				error(&curline, "syntax error");
--- a/model.c
+++ b/model.c
@@ -56,43 +56,43 @@
 static usize
 model_addposition(Model *m, Point3 p)
 {
-	return itemarrayadd(m->positions, &p, 0);
+	return itemarrayadd(m->positions, &p);
 }
 
 static usize
 model_addnormal(Model *m, Point3 n)
 {
-	return itemarrayadd(m->normals, &n, 0);
+	return itemarrayadd(m->normals, &n);
 }
 
 static usize
 model_addtexcoord(Model *m, Point2 t)
 {
-	return itemarrayadd(m->texcoords, &t, 0);
+	return itemarrayadd(m->texcoords, &t);
 }
 
 static usize
 model_addcolor(Model *m, Color c)
 {
-	return itemarrayadd(m->colors, &c, 0);
+	return itemarrayadd(m->colors, &c);
 }
 
 static usize
 model_addtangent(Model *m, Point3 T)
 {
-	return itemarrayadd(m->tangents, &T, 0);
+	return itemarrayadd(m->tangents, &T);
 }
 
 static usize
 model_addvert(Model *m, Vertex v)
 {
-	return itemarrayadd(m->verts, &v, 0);
+	return itemarrayadd(m->verts, &v);
 }
 
 static usize
 model_addprim(Model *m, Primitive P)
 {
-	return itemarrayadd(m->prims, &P, 0);
+	return itemarrayadd(m->prims, &P);
 }
 
 static int
@@ -196,4 +196,194 @@
 	rmitemarray(m->verts);
 	rmitemarray(m->prims);
 	free(m);
+}
+
+void
+compactmodel(Model *m)
+{
+	ItemArray *a1, *a2;
+	Point3 *p1, *p2, *pb, *pe;
+	Point2 *t1, *t2, *tb, *te;
+	Vertex *v, *v1, *v2, *vb, *ve;
+	Primitive *P, *P1, *P2, *Pb, *Pe;
+	void *vp;
+	usize len0, i, j, k;
+
+	a1 = m->positions;
+	pb = a1->items;
+	pe = pb + a1->nitems;
+	len0 = a1->nitems;
+	a2 = m->verts;
+	vb = a2->items;
+	ve = vb + a2->nitems;
+
+	for(p1 = pb, i = 0; p1 < pe; p1++, i++)
+	for(p2 = p1+1, j = i+1; p2 < pe; p2++, j++)
+		if(memcmp(p1, p2, sizeof(Point3)) == 0){
+			if(p2 < --pe)
+				memmove(p2, p2+1, (pe - p2)*sizeof(Point3));
+			/* reindex verts */
+			for(v = vb; v < ve; v++)
+				if(v->p == j)
+					v->p = i;
+				else if(v->p > j)
+					v->p--;
+		}
+	a1->nitems = pe - pb;
+	if(a1->nitems != len0){
+		vp = realloc(a1->items, a1->nitems * a1->itemsize);
+		if(vp == nil)
+			fprint(2, "not enough memory to shrink positions array.\n");
+		else
+			a1->items = vp;
+	}
+
+	a1 = m->normals;
+	pb = a1->items;
+	pe = pb + a1->nitems;
+	len0 = a1->nitems;
+
+	for(p1 = pb, i = 0; p1 < pe; p1++, i++)
+	for(p2 = p1+1, j = i+1; p2 < pe; p2++, j++)
+		if(memcmp(p1, p2, sizeof(Point3)) == 0){
+			if(p2 < --pe)
+				memmove(p2, p2+1, (pe - p2)*sizeof(Point3));
+			/* reindex verts */
+			for(v = vb; v < ve; v++)
+				if(v->n == j)
+					v->n = i;
+				else if(v->n > j)
+					v->n--;
+		}
+	a1->nitems = pe - pb;
+	if(a1->nitems != len0){
+		vp = realloc(a1->items, a1->nitems * a1->itemsize);
+		if(vp == nil)
+			fprint(2, "not enough memory to shrink normals array.\n");
+		else
+			a1->items = vp;
+	}
+
+	a1 = m->texcoords;
+	tb = a1->items;
+	te = tb + a1->nitems;
+	len0 = a1->nitems;
+
+	for(t1 = tb, i = 0; t1 < te; t1++, i++)
+	for(t2 = t1+1, j = i+1; t2 < te; t2++, j++)
+		if(memcmp(t1, t2, sizeof(Point2)) == 0){
+			if(t2 < --te)
+				memmove(t2, t2+1, (te - t2)*sizeof(Point2));
+			/* reindex verts */
+			for(v = vb; v < ve; v++)
+				if(v->uv == j)
+					v->uv = i;
+				else if(v->uv > j)
+					v->uv--;
+		}
+	a1->nitems = te - tb;
+	if(a1->nitems != len0){
+		vp = realloc(a1->items, a1->nitems * a1->itemsize);
+		if(vp == nil)
+			fprint(2, "not enough memory to shrink texcoords array.\n");
+		else
+			a1->items = vp;
+	}
+
+	a1 = m->colors;
+	pb = a1->items;
+	pe = pb + a1->nitems;
+	len0 = a1->nitems;
+
+	for(p1 = pb, i = 0; p1 < pe; p1++, i++)
+	for(p2 = p1+1, j = i+1; p2 < pe; p2++, j++)
+		if(memcmp(p1, p2, sizeof(Point3)) == 0){
+			if(p2 < --pe)
+				memmove(p2, p2+1, (pe - p2)*sizeof(Point3));
+			/* reindex verts */
+			for(v = vb; v < ve; v++)
+				if(v->c == j)
+					v->c = i;
+				else if(v->c > j)
+					v->c--;
+		}
+	a1->nitems = pe - pb;
+	if(a1->nitems != len0){
+		vp = realloc(a1->items, a1->nitems * a1->itemsize);
+		if(vp == nil)
+			fprint(2, "not enough memory to shrink colors array.\n");
+		else
+			a1->items = vp;
+	}
+
+	a1 = m->tangents;
+	pb = a1->items;
+	pe = pb + a1->nitems;
+	len0 = a1->nitems;
+	a2 = m->prims;
+	Pb = a2->items;
+	Pe = Pb + a2->nitems;
+
+	for(p1 = pb, i = 0; p1 < pe; p1++, i++)
+	for(p2 = p1+1, j = i+1; p2 < pe; p2++, j++)
+		if(memcmp(p1, p2, sizeof(Point3)) == 0){
+			if(p2 < --pe)
+				memmove(p2, p2+1, (pe - p2)*sizeof(Point3));
+			/* reindex prims */
+			for(P = Pb; P < Pe; P++)
+				if(P->tangent == j)
+					P->tangent = i;
+				else if(P->tangent > j)
+					P->tangent--;
+		}
+	a1->nitems = pe - pb;
+	if(a1->nitems != len0){
+		vp = realloc(a1->items, a1->nitems * a1->itemsize);
+		if(vp == nil)
+			fprint(2, "not enough memory to shrink tangents array.\n");
+		else
+			a1->items = vp;
+	}
+
+	a1 = m->verts;
+	vb = a1->items;
+	ve = vb + a1->nitems;
+	len0 = a1->nitems;
+
+	for(v1 = vb, i = 0; v1 < ve; v1++, i++)
+	for(v2 = v1+1, j = i+1; v2 < ve; v2++, j++)
+		if(memcmp(v1, v2, sizeof(Vertex)) == 0){
+			if(v2 < --ve)
+				memmove(v2, v2+1, (ve - v2)*sizeof(Vertex));
+			/* reindex prims */
+			for(P = Pb; P < Pe; P++)
+				for(k = 0; k < P->type+1; k++)
+					if(P->v[k] == j)
+						P->v[k] = i;
+					else if(P->v[k] > j)
+						P->v[k]--;
+		}
+	a1->nitems = ve - vb;
+	if(a1->nitems != len0){
+		vp = realloc(a1->items, a1->nitems * a1->itemsize);
+		if(vp == nil)
+			fprint(2, "not enough memory to shrink vertex array.\n");
+		else
+			a1->items = vp;
+	}
+
+	len0 = a2->nitems;
+	for(P1 = Pb, i = 0; P1 < Pe; P1++, i++)
+	for(P2 = P1+1, j = i+1; P2 < Pe; P2++, j++)
+		if(memcmp(P1, P2, sizeof(Primitive)) == 0)
+			if(P2 < --Pe)
+				memmove(P2, P2+1, (Pe - P2)*sizeof(Primitive));
+	a2->nitems = Pe - Pb;
+	if(a2->nitems != len0){
+		vp = realloc(a2->items, a2->nitems * a2->itemsize);
+		if(vp == nil)
+			fprint(2, "not enough memory to shrink vertex array.\n");
+		else
+			a2->items = vp;
+	}
 }
--