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;
+ }
}
--
⑨