ref: 81d07752e717d2dece4e5f9dded3eb379cbe27f2
parent: 8eb98b6c111e148bdf2285016068cbea6110dfbc
author: rodri <rgl@antares-labs.eu>
date: Sat Jun 28 16:15:25 EDT 2025
implement indexed vertex attributes and vertices for Model now it matches the file format—model(6)—and simplifies import and export. it also simplifies the conversion to/from OBJ, and should be the same with other indexed attributes formats.
--- a/TODO.md
+++ b/TODO.md
@@ -8,19 +8,10 @@
- [ ] Avoid writing the same texture multiple times under different names in exportmodel(2)
- [ ] Add wireframe rendering by a reasonable interface and method
- [ ] Find out why the A-buffer takes so much memory (enough to run OOM on a 32GB term!)
-- [ ] Review the idea of using indexed properties for the vertices
- - This has become a more pressing matter with 3dee/toobj (the
- Model to OBJ conversion tool) because its quite inefficient
- and generates very large .obj files with unnecessary
- redundancy: e.g., with a box, where instead of storing one
- normal per every face, we store the same normal on the six
- vertices (three per triangle) that make up the face.
+- [+] Review the idea of using indexed properties for the vertices
- [+] Create an internal Vertex type
- - I want to get rid of the Vertex.(Vertexattrs|mtl|tangent)
- properties, as they are only used during rasterization.
- This will affect the Primitive as well, so it will probably
- require an internal Primitive type.
- [ ] See if prims can be ordered front-to-back before rasterizing (quick Z-buffer discard)
- It might be better to add it as a Camera.rendopts flag, for
transparency rendering without the A-buffer.
- [ ] Implement decals
+- [ ] Implement Model deduplication/compaction routine
--- a/camera.c
+++ b/camera.c
@@ -40,36 +40,59 @@
static Model *
mkskyboxmodel(void)
{
- static Point3 axes[3] = {{0,1,0,0}, {1,0,0,0}, {0,0,1,0}};
- static Point3 center = {0,0,0,1};
+ static int indices[] = {
+ /* front */
+ 0, 1, 4+1, 0, 4+1, 4+0,
+ /* right */
+ 1, 2, 4+2, 1, 4+2, 4+1,
+ /* bottom */
+ 0, 3, 2, 0, 2, 1,
+ /* back */
+ 3, 4+3, 4+2, 3, 4+2, 2,
+ /* left */
+ 0, 4+0, 4+3, 0, 4+3, 3,
+ /* top */
+ 4+0, 4+1, 4+2, 4+0, 4+2, 4+3,
+ };
Model *m;
- Primitive t[2];
- Point3 p, v1, v2;
- int i, j, k;
+ Primitive t;
+ Vertex v;
+ Point3 p;
+ int i, k;
+// int f, j;
m = newmodel();
- memset(t, 0, sizeof t);
- t[0].type = t[1].type = PTriangle;
+ t = mkprim(PTriangle);
+ v = mkvert();
- p = Vec3(-0.5,-0.5,0.5);
- v1 = Vec3(1,0,0);
- v2 = Vec3(0,1,0);
- t[0].v[0].p = addpt3(center, p);
- t[0].v[1].p = addpt3(center, addpt3(p, v1));
- t[0].v[2].p = addpt3(center, addpt3(p, addpt3(v1, v2)));
- t[1].v[0] = t[0].v[0];
- t[1].v[1] = t[0].v[2];
- t[1].v[2].p = addpt3(center, addpt3(p, v2));
+ /* build bottom and top quads around y-axis */
+ p = Pt3(-0.5,-0.5,0.5,1);
+ for(i = 0; i < 8; i++){
+ if(i == 4)
+ p.y++;
+ v.p = m->addposition(m, p);
+ m->addvert(m, v);
+ p = qrotate(p, Vec3(0,1,0), PI/2);
+ }
- for(i = 0; i < 6; i++){
- for(j = 0; j < 2; j++)
- for(k = 0; k < 3; k++)
- if(i > 0)
- t[j].v[k].p = qrotate(t[j].v[k].p, axes[i%3], PI/2);
+ for(i = 0; i < nelem(indices); i++){
+// f = i/6 % 6;
+// j = i/3 % 2;
+ k = i % 3;
+ t.v[k] = indices[i];
+ if(k == 3-1){
+ m->addprim(m, t);
- m->addprim(m, t[0]);
- m->addprim(m, t[1]);
+// Point3 p0, p1;
+// for(k = 0; k < 3; k++){
+// p0 = *(Point3*)itemarrayget(m->positions, t.v[k]);
+// p1 = *(Point3*)itemarrayget(m->positions, t.v[(k+1)%3]);
+// if(eqpt3(p0, p1))
+// fprint(2, "face %d disfigured (tri #%d, verts %d %V and %d %V)\n", f, j, k, p0, k+1, p1);
+// }
+ }
}
+
return m;
}
--- a/graphics.h
+++ b/graphics.h
@@ -50,8 +50,12 @@
/* vertex attribute types */
VAPoint = 0,
VANumber,
+
+ /* itemarray */
+ NaI = ~0ULL, /* not an index */
};
+typedef struct ItemArray ItemArray;
typedef struct Color Color;
typedef struct Texture Texture;
typedef struct Cubemap Cubemap;
@@ -80,6 +84,13 @@
typedef struct Viewport Viewport;
typedef struct Camera Camera;
+struct ItemArray
+{
+ void *items;
+ usize nitems;
+ usize itemsize;
+};
+
struct Color
{
double r, g, b, a;
@@ -138,10 +149,10 @@
struct Vertex
{
- Point3 p; /* position */
- Point3 n; /* surface normal */
- Color c; /* shading color */
- Point2 uv; /* texture coordinate */
+ usize p; /* position */
+ usize n; /* surface normal */
+ usize uv; /* texture coordinate */
+ usize c; /* shading color */
};
/*
@@ -151,7 +162,10 @@
*/
struct BVertex
{
- Vertex;
+ Point3 p; /* position */
+ Point3 n; /* surface normal */
+ Point2 uv; /* texture coordinate */
+ Color c; /* shading color */
Material *mtl;
Point3 tangent;
Vertexattrs; /* attributes (varyings) */
@@ -186,19 +200,30 @@
struct Primitive
{
int type;
- Vertex v[3];
+ usize v[3];
+ usize tangent; /* used for normal mapping */
Material *mtl;
- Point3 tangent; /* used for normal mapping */
};
struct Model
{
- Primitive *prims;
- ulong nprims;
+ ItemArray *positions;
+ ItemArray *normals;
+ ItemArray *texcoords;
+ ItemArray *colors;
+ ItemArray *tangents;
+ ItemArray *verts;
+ ItemArray *prims;
Material *materials;
ulong nmaterials;
- int (*addprim)(Model*, Primitive);
+ usize (*addposition)(Model*, Point3);
+ usize (*addnormal)(Model*, Point3);
+ usize (*addtexcoord)(Model*, Point2);
+ usize (*addcolor)(Model*, Color);
+ usize (*addtangent)(Model*, Point3);
+ usize (*addvert)(Model*, Vertex);
+ usize (*addprim)(Model*, Primitive);
int (*addmaterial)(Model*, Material);
Material *(*getmaterial)(Model*, char*);
};
@@ -428,10 +453,12 @@
/* marshal */
Model *readmodel(int);
-usize writemodel(int, Model*, int);
-int exportmodel(char*, Model*, int);
+usize writemodel(int, Model*);
+int exportmodel(char*, Model*);
/* scene */
+Vertex mkvert(void);
+Primitive mkprim(int);
Material *newmaterial(char*);
void delmaterial(Material*);
Model *newmodel(void);
@@ -475,6 +502,14 @@
int eqpt3(Point3, Point3);
Memimage *rgba(ulong);
Memimage *dupmemimage(Memimage*);
+
+/* itemarray */
+ItemArray *mkitemarray(usize);
+usize itemarrayadd(ItemArray*, void*, int);
+void *itemarrayget(ItemArray*, usize);
+usize copyitemarray(ItemArray*, ItemArray*);
+ItemArray *dupitemarray(ItemArray*);
+void rmitemarray(ItemArray*);
/* color */
ulong col2ul(Color);
--- a/internal.h
+++ b/internal.h
@@ -24,8 +24,8 @@
{
int type;
BVertex v[3];
- Material *mtl;
Point3 tangent; /* used for normal mapping */
+ Material *mtl;
};
struct Polygon
--- /dev/null
+++ b/itemarray.c
@@ -1,0 +1,86 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <thread.h>
+#include <draw.h>
+#include <memdraw.h>
+#include <geometry.h>
+#include "graphics.h"
+#include "internal.h"
+
+ItemArray *
+mkitemarray(usize is)
+{
+ ItemArray *a;
+
+ a = _emalloc(sizeof *a);
+ memset(a, 0, sizeof *a);
+ a->itemsize = is;
+ return a;
+}
+
+usize
+itemarrayadd(ItemArray *a, void *i, int dedup)
+{
+ 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);
+ p = a->items;
+ p += idx*a->itemsize;
+ memmove(p, i, a->itemsize);
+ return idx;
+}
+
+void *
+itemarrayget(ItemArray *a, usize idx)
+{
+ char *p;
+
+ if(idx >= a->nitems)
+ return nil;
+
+ p = a->items;
+ p += idx*a->itemsize;
+ return p;
+}
+
+usize
+copyitemarray(ItemArray *d, ItemArray *s)
+{
+ usize len;
+
+ assert(d->itemsize == s->itemsize);
+ len = s->nitems * s->itemsize;
+
+ free(d->items);
+ d->items = _emalloc(len);
+ d->nitems = s->nitems;
+ memmove(d->items, s->items, len);
+ return d->nitems;
+}
+
+ItemArray *
+dupitemarray(ItemArray *a)
+{
+ ItemArray *na;
+
+ na = mkitemarray(a->itemsize);
+ copyitemarray(na, a);
+ return na;
+}
+
+void
+rmitemarray(ItemArray *a)
+{
+ free(a->items);
+ free(a);
+}
--- a/marshal.c
+++ b/marshal.c
@@ -9,7 +9,6 @@
#include "internal.h"
enum {
- NaI = ~0ULL, /* not an index */
MTLHTSIZ = 17,
};
@@ -20,32 +19,9 @@
usize line;
};
-typedef struct IArray IArray;
-typedef struct Wirevert Wirevert;
-typedef struct Wireprim Wireprim;
typedef struct Mtlentry Mtlentry;
typedef struct Mtltab Mtltab;
-struct IArray
-{
- void *items;
- usize nitems;
- usize itemsize;
-};
-
-struct Wirevert
-{
- usize p, n, t, c;
-};
-
-struct Wireprim
-{
- int nv;
- usize v[3];
- usize T;
- char *mtlname;
-};
-
struct Mtlentry
{
Material;
@@ -85,58 +61,6 @@
werrstr("%s", buf);
}
-static IArray *
-mkitemarray(usize is)
-{
- IArray *a;
-
- a = _emalloc(sizeof *a);
- memset(a, 0, sizeof *a);
- a->itemsize = is;
- return a;
-}
-
-static usize
-itemarrayadd(IArray *a, void *i, int dedup)
-{
- 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);
- p = a->items;
- p += idx*a->itemsize;
- memmove(p, i, a->itemsize);
- return idx;
-}
-
-static void *
-itemarrayget(IArray *a, usize idx)
-{
- char *p;
-
- if(idx >= a->nitems)
- return nil;
-
- p = a->items;
- p += idx*a->itemsize;
- return p;
-}
-
-static void
-rmitemarray(IArray *a)
-{
- free(a->items);
- free(a);
-}
-
static uint
hash(char *s)
{
@@ -239,7 +163,7 @@
readmodel(int fd)
{
Curline curline;
- IArray *pa, *na, *ta, *ca, *Ta, *va, *Pa;
+ ItemArray *pa, *na, *ta, *ca, *Ta, *va, *Pa;
Mtltab *mtltab;
Mtlentry *me;
Point3 p, n, T;
@@ -246,7 +170,7 @@
Point2 t;
Color c;
Vertex v;
- Primitive P;
+ Primitive P, *prim;
Material mtl;
Model *m;
Memimage *mi;
@@ -254,7 +178,6 @@
void *vp;
char *line, *f[10], *s, assets[200], buf[256];
usize idx, i;
- ulong primidx;
int nf, nv, inamaterial, texfd;
n.w = T.w = 0;
@@ -278,9 +201,9 @@
if(fd2path(fd, curline.file, sizeof curline.file) != 0)
sysfatal("fd2path: %r");
if((s = strrchr(curline.file, '/')) != nil){
- *s = 0;
+ *s++ = 0;
snprint(assets, sizeof assets, "%s", curline.file);
- memmove(curline.file, s+1, strlen(s+1) + 1);
+ memmove(curline.file, s, strlen(s) + 1);
}else{
assets[0] = '.';
assets[1] = 0;
@@ -477,7 +400,7 @@
error(&curline, "no position at idx %llud", idx);
goto getout;
}
- v.p = *(Point3*)vp;
+ v.p = idx;
if(strcmp(f[2], "-") != 0){
idx = strtoul(f[2], nil, 10);
@@ -486,7 +409,7 @@
error(&curline, "no normal at idx %llud", idx);
goto getout;
}
- v.n = *(Point3*)vp;
+ v.n = idx;
}
if(strcmp(f[3], "-") != 0){
@@ -496,7 +419,7 @@
error(&curline, "no texture at idx %llud", idx);
goto getout;
}
- v.uv = *(Point2*)vp;
+ v.uv = idx;
}
if(strcmp(f[4], "-") != 0){
@@ -506,7 +429,7 @@
error(&curline, "no color at idx %llud", idx);
goto getout;
}
- v.c = *(Color*)vp;
+ v.c = idx;
}
itemarrayadd(va, &v, 0);
@@ -529,7 +452,7 @@
error(&curline, "no vertex at idx %llud", idx);
goto getout;
}
- P.v[0] = *(Vertex*)vp;
+ P.v[0] = idx;
/* ignore 4th field (nf == 4) */
@@ -548,7 +471,7 @@
vp = itemarrayget(va, idx);
if(vp == nil)
goto novertex;
- P.v[0] = *(Vertex*)vp;
+ P.v[0] = idx;
if(nf < 4){
notenough:
@@ -559,7 +482,7 @@
vp = itemarrayget(va, idx);
if(vp == nil)
goto novertex;
- P.v[1] = *(Vertex*)vp;
+ P.v[1] = idx;
/* ignore 5th field (nf == 5) */
@@ -578,7 +501,7 @@
vp = itemarrayget(va, idx);
if(vp == nil)
goto novertex;
- P.v[0] = *(Vertex*)vp;
+ P.v[0] = idx;
if(nf < 4)
goto notenough;
@@ -586,7 +509,7 @@
vp = itemarrayget(va, idx);
if(vp == nil)
goto novertex;
- P.v[1] = *(Vertex*)vp;
+ P.v[1] = idx;
if(nf < 5)
goto notenough;
@@ -594,7 +517,7 @@
vp = itemarrayget(va, idx);
if(vp == nil)
goto novertex;
- P.v[2] = *(Vertex*)vp;
+ P.v[2] = idx;
if(nf < 6){
error(&curline, "missing triangle tangent field");
@@ -607,7 +530,7 @@
error(&curline, "no tangent at idx %llud", idx);
goto getout;
}
- P.tangent = *(Point3*)vp;
+ P.tangent = idx;
}
if(nf == 7){
@@ -646,11 +569,18 @@
m = newmodel();
mtltabloadmodel(m, mtltab);
+ copyitemarray(m->positions, pa);
+ copyitemarray(m->normals, na);
+ copyitemarray(m->texcoords, ta);
+ copyitemarray(m->colors, ca);
+ copyitemarray(m->tangents, Ta);
+ copyitemarray(m->verts, va);
+ copyitemarray(m->prims, Pa);
for(i = 0; i < Pa->nitems; i++){
- primidx = m->addprim(m, *(Primitive*)itemarrayget(Pa, i));
- if(m->prims[primidx].mtl != nil){
- me = mtltabget(mtltab, m->prims[primidx].mtl->name);
- m->prims[primidx].mtl = &m->materials[me->idx];
+ prim = itemarrayget(m->prims, i);
+ if(prim->mtl != nil){
+ me = mtltabget(mtltab, prim->mtl->name);
+ prim->mtl = &m->materials[me->idx];
}
}
@@ -756,13 +686,13 @@
}
static int
-Bprintv(Biobuf *b, Wirevert *v)
+Bprintv(Biobuf *b, Vertex *v)
{
int n;
n = Bprint(b, "v %llud", v->p);
n += Bprintidx(b, v->n);
- n += Bprintidx(b, v->t);
+ n += Bprintidx(b, v->uv);
n += Bprintidx(b, v->c);
n += Bprint(b, "\n");
return n;
@@ -769,17 +699,17 @@
}
static int
-BprintP(Biobuf *b, Wireprim *p)
+BprintP(Biobuf *b, Primitive *p)
{
char *s;
int n, i;
- n = Bprint(b, "P %d", p->nv);
- for(i = 0; i < p->nv; i++)
+ n = Bprint(b, "P %d", p->type+1);
+ for(i = 0; i < p->type+1; i++)
n += Bprintidx(b, p->v[i]);
- n += Bprintidx(b, p->T);
- if(p->mtlname != nil){
- s = quotestrdup(p->mtlname);
+ n += Bprintidx(b, p->tangent);
+ if(p->mtl != nil){
+ s = quotestrdup(p->mtl->name);
if(s == nil)
sysfatal("quotestrdup: %r");
n += Bprint(b, " %s", s);
@@ -844,79 +774,34 @@
}
usize
-writemodel(int fd, Model *m, int dedup)
+writemodel(int fd, Model *m)
{
- IArray *pa, *na, *ta, *ca, *Ta, *va, *Pa;
- Wirevert v;
- Wireprim P;
- Primitive *p, *ep;
Biobuf *out;
- usize n;
- int i;
+ usize n, i;
out = Bfdopen(fd, OWRITE);
if(out == nil)
sysfatal("Bfdopen: %r");
- pa = mkitemarray(sizeof(Point3));
- na = mkitemarray(sizeof(Point3));
- ta = mkitemarray(sizeof(Point2));
- ca = mkitemarray(sizeof(Color));
- Ta = mkitemarray(sizeof(Point3));
- va = mkitemarray(sizeof(Wirevert));
- Pa = mkitemarray(sizeof(Wireprim));
-
n = 0;
- p = m->prims;
- ep = p + m->nprims;
-
- while(p < ep){
- memset(&P, 0, sizeof P);
-
- P.nv = p->type+1;
- for(i = 0; i < P.nv; i++){
- v.p = itemarrayadd(pa, &p->v[i].p, dedup);
- v.n = eqpt3(p->v[i].n, ZP3)?
- NaI: itemarrayadd(na, &p->v[i].n, dedup);
- v.t = p->v[i].uv.w != 1?
- NaI: itemarrayadd(ta, &p->v[i].uv, dedup);
- v.c = p->v[i].c.a == 0?
- NaI: itemarrayadd(ca, &p->v[i].c, dedup);
- P.v[i] = itemarrayadd(va, &v, dedup);
- }
- P.T = eqpt3(p->tangent, ZP3)?
- NaI: itemarrayadd(Ta, &p->tangent, dedup);
- P.mtlname = p->mtl != nil? p->mtl->name: nil;
-
- itemarrayadd(Pa, &P, 0);
- p++;
- }
-
for(i = 0; i < m->nmaterials; i++)
n += Bprintmtl(out, &m->materials[i]);
- for(i = 0; i < pa->nitems; i++)
- n += Bprintp(out, itemarrayget(pa, i));
- for(i = 0; i < na->nitems; i++)
- n += Bprintn(out, itemarrayget(na, i));
- for(i = 0; i < ta->nitems; i++)
- n += Bprintt(out, itemarrayget(ta, i));
- for(i = 0; i < ca->nitems; i++)
- n += Bprintc(out, itemarrayget(ca, i));
- for(i = 0; i < Ta->nitems; i++)
- n += BprintT(out, itemarrayget(Ta, i));
- for(i = 0; i < va->nitems; i++)
- n += Bprintv(out, itemarrayget(va, i));
- for(i = 0; i < Pa->nitems; i++)
- n += BprintP(out, itemarrayget(Pa, i));
+ for(i = 0; i < m->positions->nitems; i++)
+ n += Bprintp(out, itemarrayget(m->positions, i));
+ for(i = 0; i < m->normals->nitems; i++)
+ n += Bprintn(out, itemarrayget(m->normals, i));
+ for(i = 0; i < m->texcoords->nitems; i++)
+ n += Bprintt(out, itemarrayget(m->texcoords, i));
+ for(i = 0; i < m->colors->nitems; i++)
+ n += Bprintc(out, itemarrayget(m->colors, i));
+ for(i = 0; i < m->tangents->nitems; i++)
+ n += BprintT(out, itemarrayget(m->tangents, i));
+ for(i = 0; i < m->verts->nitems; i++)
+ n += Bprintv(out, itemarrayget(m->verts, i));
+ for(i = 0; i < m->prims->nitems; i++)
+ n += BprintP(out, itemarrayget(m->prims, i));
- rmitemarray(pa);
- rmitemarray(na);
- rmitemarray(ta);
- rmitemarray(ca);
- rmitemarray(Ta);
- rmitemarray(va);
- rmitemarray(Pa);
Bterm(out);
return n;
}
@@ -941,7 +826,7 @@
}
int
-exportmodel(char *path, Model *m, int dedup)
+exportmodel(char *path, Model *m)
{
static char Esmallbuf[] = "buf too small to hold path";
Material *mtl;
@@ -1004,7 +889,7 @@
werrstr("create: %r");
return -1;
}
- if(writemodel(fd, m, dedup) == 0){
+ if(writemodel(fd, m) == 0){
close(fd);
werrstr("writemodel: %r");
return -1;
--- a/mkfile
+++ b/mkfile
@@ -18,6 +18,7 @@
util.$O\
nanosec.$O\
marshal.$O\
+ itemarray.$O\
`{fn : { test -f $1-$objtype.s\
&& echo $1-$objtype.$O\
|| echo $1.$O };\
--- a/render.c
+++ b/render.c
@@ -549,6 +549,30 @@
wr[nwr-1].max.y = fbr->max.y;
}
+static BPrimitive *
+assembleprim(BPrimitive *d, Primitive *s, Model *m)
+{
+ Vertex *v;
+ void *vp;
+ int i;
+
+ d->type = s->type;
+ for(i = 0; i < s->type+1; i++){
+ v = itemarrayget(m->verts, s->v[i]);
+ d->v[i].p = *(Point3*)itemarrayget(m->positions, v->p);
+ vp = itemarrayget(m->normals, v->n);
+ d->v[i].n = vp != nil? *(Point3*)vp: ZP3;
+ vp = itemarrayget(m->colors, v->c);
+ d->v[i].c = vp != nil? *(Color*)vp: ZP3;
+ vp = itemarrayget(m->texcoords, v->uv);
+ d->v[i].uv = vp != nil? *(Point2*)vp: ZP2;
+ }
+ vp = itemarrayget(m->tangents, s->tangent);
+ d->tangent = vp != nil? *(Point3*)vp: ZP3;
+ d->mtl = s->mtl;
+ return d;
+}
+
static void
tiler(void *arg)
{
@@ -608,12 +632,8 @@
for(ep = params->eb; ep != params->ee; ep++){
np = 1; /* start with one. after clipping it might change */
- prim.type = ep->type;
- for(i = 0; i < prim.type+1; i++)
- prim.v[i].Vertex = ep->v[i];
- prim.mtl = ep->mtl;
- prim.tangent = ep->tangent;
- p = &prim;
+ p = assembleprim(&prim, ep, params->entity->mdl);
+
switch(p->type){
case PPoint:
p->v[0].mtl = p->mtl;
@@ -831,8 +851,8 @@
}
}
- eb = params->entity->mdl->prims;
- nprims = params->entity->mdl->nprims;
+ eb = params->entity->mdl->prims->items;
+ nprims = params->entity->mdl->prims->nitems;
ee = eb + nprims;
if(nprims <= nproc){
--- a/scene.c
+++ b/scene.c
@@ -7,6 +7,24 @@
#include "graphics.h"
#include "internal.h"
+Vertex
+mkvert(void)
+{
+ return (Vertex){NaI, NaI, NaI, NaI};
+}
+
+Primitive
+mkprim(int type)
+{
+ Primitive prim;
+
+ prim.type = type;
+ prim.v[0] = prim.v[1] = prim.v[2] = NaI;
+ prim.tangent = NaI;
+ prim.mtl = nil;
+ return prim;
+}
+
Material *
newmaterial(char *name)
{
@@ -35,14 +53,48 @@
free(mtl->name);
}
-static int
-model_addprim(Model *m, Primitive p)
+static usize
+model_addposition(Model *m, Point3 p)
{
- m->prims = _erealloc(m->prims, ++m->nprims*sizeof(*m->prims));
- m->prims[m->nprims-1] = p;
- return m->nprims-1;
+ return itemarrayadd(m->positions, &p, 0);
}
+static usize
+model_addnormal(Model *m, Point3 n)
+{
+ return itemarrayadd(m->normals, &n, 0);
+}
+
+static usize
+model_addtexcoord(Model *m, Point2 t)
+{
+ return itemarrayadd(m->texcoords, &t, 0);
+}
+
+static usize
+model_addcolor(Model *m, Color c)
+{
+ return itemarrayadd(m->colors, &c, 0);
+}
+
+static usize
+model_addtangent(Model *m, Point3 T)
+{
+ return itemarrayadd(m->tangents, &T, 0);
+}
+
+static usize
+model_addvert(Model *m, Vertex v)
+{
+ return itemarrayadd(m->verts, &v, 0);
+}
+
+static usize
+model_addprim(Model *m, Primitive P)
+{
+ return itemarrayadd(m->prims, &P, 0);
+}
+
static int
model_addmaterial(Model *m, Material mtl)
{
@@ -69,6 +121,19 @@
m = _emalloc(sizeof *m);
memset(m, 0, sizeof *m);
+ m->positions = mkitemarray(sizeof(Point3));
+ m->normals = mkitemarray(sizeof(Point3));
+ m->texcoords = mkitemarray(sizeof(Point2));
+ m->colors = mkitemarray(sizeof(Color));
+ m->tangents = mkitemarray(sizeof(Point3));
+ m->verts = mkitemarray(sizeof(Vertex));
+ m->prims = mkitemarray(sizeof(Primitive));
+ m->addposition = model_addposition;
+ m->addnormal = model_addnormal;
+ m->addtexcoord = model_addtexcoord;
+ m->addcolor = model_addcolor;
+ m->addtangent = model_addtangent;
+ m->addvert = model_addvert;
m->addprim = model_addprim;
m->addmaterial = model_addmaterial;
m->getmaterial = model_getmaterial;
@@ -79,6 +144,7 @@
dupmodel(Model *m)
{
Model *nm;
+ Primitive *prim, *nprim;
int i;
if(m == nil)
@@ -98,13 +164,18 @@
sysfatal("strdup: %r");
}
}
- if(m->nprims > 0){
- nm->nprims = m->nprims;
- nm->prims = _emalloc(nm->nprims*sizeof(*nm->prims));
- for(i = 0; i < m->nprims; i++){
- nm->prims[i] = m->prims[i];
- if(nm->nmaterials > 0 && m->prims[i].mtl != nil)
- nm->prims[i].mtl = &nm->materials[m->prims[i].mtl - m->materials];
+ nm->positions = dupitemarray(m->positions);
+ nm->normals = dupitemarray(m->normals);
+ nm->texcoords = dupitemarray(m->texcoords);
+ nm->colors = dupitemarray(m->colors);
+ nm->tangents = dupitemarray(m->tangents);
+ nm->verts = dupitemarray(m->verts);
+ nm->prims = dupitemarray(m->prims);
+ for(i = 0; i < m->prims->nitems && nm->nmaterials > 0; i++){
+ prim = itemarrayget(m->prims, i);
+ if(prim->mtl != nil){
+ nprim = itemarrayget(nm->prims, i);
+ nprim->mtl = &nm->materials[prim->mtl - m->materials];
}
}
return nm;
@@ -119,7 +190,13 @@
while(m->nmaterials--)
delmaterial(&m->materials[m->nmaterials]);
free(m->materials);
- free(m->prims);
+ rmitemarray(m->positions);
+ rmitemarray(m->normals);
+ rmitemarray(m->texcoords);
+ rmitemarray(m->colors);
+ rmitemarray(m->tangents);
+ rmitemarray(m->verts);
+ rmitemarray(m->prims);
free(m);
}
--
⑨