ref: 380057f08bc96785ec1fc7801e457ff3d08e91c0
parent: 56c0e4ec2df1bce0e7345c90bf42628b3e1f77e7
author: rodri <rgl@antares-labs.eu>
date: Sat Jun 28 16:30:56 EDT 2025
use the new indexed attributes and vertices Model structure i took the chance to clean, fix and make some improvements in some of the tools: - solar: was leaking an Entity every time the user made a selection. - vis: didn't initialize the mkblendtest() model correctly. also got rid of an ιnception mode warning.
--- a/med.c
+++ b/med.c
@@ -239,86 +239,114 @@
materializefrustum(void)
{
Primitive l;
+ Vertex v;
Point3 p[4];
- int i;
+ usize vidx0;
+ int i, j;
p[0] = Pt3(0,0,1,1);
p[1] = Pt3(Dx(cam->view->r),0,1,1);
p[2] = Pt3(Dx(cam->view->r),Dy(cam->view->r),1,1);
p[3] = Pt3(0,Dy(cam->view->r),1,1);
- memset(&l, 0, sizeof l);
- l.type = PLine;
- l.v[0].c = l.v[1].c = Pt3(1,1,1,1);
+ l = mkprim(PLine);
+ v = mkvert();
+ v.c = model->addcolor(model, Pt3(1,1,1,1));
- for(i = 0; i < nelem(p); i++){
- /* front frame */
- l.v[0].p = world2model(subject, viewport2world(cam, p[i]));
- l.v[1].p = world2model(subject, viewport2world(cam, p[(i+1)%nelem(p)]));
- qlock(&scenelk);
- model->addprim(model, l);
- qunlock(&scenelk);
+ qlock(&scenelk);
+ vidx0 = model->verts->nitems;
+ /* add front, middle and back frames' vertices */
+ for(i = 0; i < 3; i++)
+ for(j = 0; j < nelem(p); j++){
+ v.p = model->addposition(model, world2model(subject, viewport2world(cam, p[i])));
+ p[i] = addpt3(p[i], Vec3(0,0,0.5));
+ model->addvert(model, v);
+ }
- /* middle frame */
- l.v[0].p = world2model(subject, viewport2world(cam, subpt3(p[i], Vec3(0,0,0.5))));
- l.v[1].p = world2model(subject, viewport2world(cam, subpt3(p[(i+1)%nelem(p)], Vec3(0,0,0.5))));
- qlock(&scenelk);
- model->addprim(model, l);
- qunlock(&scenelk);
+ /* build the frames */
+ for(i = 0; i < 3; i++)
+ for(j = 1; j <= nelem(p); j++){
+ l.v[0] = vidx0 + 4*i + j-1;
+ l.v[1] = vidx0 + 4*i + j%4;
+ model->addprim(model, l);
+ }
- /* back frame */
- l.v[0].p = world2model(subject, viewport2world(cam, subpt3(p[i], Vec3(0,0,1))));
- l.v[1].p = world2model(subject, viewport2world(cam, subpt3(p[(i+1)%nelem(p)], Vec3(0,0,1))));
- qlock(&scenelk);
- model->addprim(model, l);
- qunlock(&scenelk);
-
- /* struts */
- l.v[1].p = world2model(subject, viewport2world(cam, p[i]));
- qlock(&scenelk);
- model->addprim(model, l);
- qunlock(&scenelk);
- }
+ /* connect the frames with struts */
+ for(i = 0; i < nelem(p); i++)
+ for(j = 1; j < 3; j++){
+ l.v[0] = vidx0 + 4*(j-1) + i;
+ l.v[1] = vidx0 + 4*j + i;
+ model->addprim(model, l);
+ }
+ qunlock(&scenelk);
}
void
addcube(void)
{
- static Point3 axis[3] = {{0,1,0,0}, {1,0,0,0}, {0,0,1,0}};
- Primitive t[2];
- Point3 p, v1, v2;
- int i, j, k;
+ static int pindices[] = {
+ /* front */
+ 0, 1, 4+1, 4+0,
+ /* bottom */
+ 0, 3, 2, 1,
+ /* right */
+ 1, 2, 4+2, 4+1,
+ /* back */
+ 3, 4+3, 4+2, 2,
+ /* top */
+ 4+0, 4+1, 4+2, 4+3,
+ /* left */
+ 0, 4+0, 4+3, 3,
+ };
+ static Point3 axes[3] = {{0,1,0,0}, {1,0,0,0}, {0,0,1,0}};
+ Primitive t;
+ Vertex v;
+ Point3 p;
+ usize pidx0, nidx0, vidx0;
+ int i;
- memset(t, 0, sizeof t);
- t[0].type = t[1].type = PTriangle;
+ t = mkprim(PTriangle);
+ v = mkvert();
- /* build the first face/quad, facing the positive z axis */
- 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[0].n = t[0].v[1].n = t[0].v[2].n = t[1].v[2].n = Vec3(0,0,1);
- t[0].v[1].p = addpt3(center, addpt3(p, v1));
- t[0].v[2].p = addpt3(center, addpt3(p, addpt3(v1, v2)));
- t[0].v[0].c = t[0].v[1].c = t[0].v[2].c = Pt3(1,1,1,1);
- 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));
- t[1].v[2].c = Pt3(1,1,1,1);
+ v.c = model->addcolor(model, Pt3(1,1,1,1));
- /* make a cube by rotating the reference face */
+ qlock(&scenelk);
+ /* build bottom and top vertex quads around y-axis */
+ pidx0 = model->positions->nitems;
+ p = Pt3(-0.5,-0.5,0.5,1);
+ for(i = 0; i < 8; i++){
+ if(i == 4)
+ p.y++;
+ model->addposition(model, p);
+ p = qrotate(p, Vec3(0,1,0), PI/2);
+ }
+
+ /* build normals */
+ nidx0 = model->normals->nitems;
+ p = Vec3(0,0,1);
for(i = 0; i < 6; i++){
- if(i > 0)
- for(j = 0; j < 2; j++)
- for(k = 0; k < 3; k++){
- t[j].v[k].p = qrotate(t[j].v[k].p, axis[i%3], PI/2);
- t[j].v[k].n = qrotate(t[j].v[k].n, axis[i%3], PI/2);
- }
+ model->addnormal(model, p);
+ p = qrotate(p, axes[(i+1)%3], PI/2);
+ }
- qlock(&scenelk);
- model->addprim(model, t[0]);
- model->addprim(model, t[1]);
- qunlock(&scenelk);
+ /* build vertices */
+ vidx0 = model->verts->nitems;
+ for(i = 0; i < nelem(pindices); i++){
+ v.p = pidx0 + pindices[i];
+ v.n = nidx0 + i/4;
+ model->addvert(model, v);
}
+
+ /* triangulate vertices */
+ for(i = 0; i < 6; i++){
+ t.v[0] = vidx0 + 4*i + 0;
+ t.v[1] = vidx0 + 4*i + 1;
+ t.v[2] = vidx0 + 4*i + 2;
+ model->addprim(model, t);
+ t.v[1] = vidx0 + 4*i + 2;
+ t.v[2] = vidx0 + 4*i + 3;
+ model->addprim(model, t);
+ }
+ qunlock(&scenelk);
}
static void
@@ -326,25 +354,33 @@
{
Entity *e;
Model *m;
- Primitive prims[3];
+ Vertex v;
+ Primitive l;
+ int i;
m = newmodel();
e = newentity("basis", m);
- memset(prims, 0, sizeof prims);
- prims[0].type = prims[1].type = prims[2].type = PLine;
- prims[0].v[0].p = prims[1].v[0].p = prims[2].v[0].p = center;
- prims[0].v[0].c = prims[1].v[0].c = prims[2].v[0].c = Pt3(0,0,0,1);
- prims[0].v[1].p = addpt3(center, e->bx);
- prims[0].v[1].c = Pt3(1,0,0,1);
- prims[1].v[1].p = addpt3(center, e->by);
- prims[1].v[1].c = Pt3(0,1,0,1);
- prims[2].v[1].p = addpt3(center, e->bz);
- prims[2].v[1].c = Pt3(0,0,1,1);
+ v = mkvert();
+ v.p = m->addposition(m, center);
+ v.c = m->addcolor(m, Pt3(0,0,0,1));
+ m->addvert(m, v);
+ v.p = m->addposition(m, addpt3(center, e->bx));
+ v.c = m->addcolor(m, Pt3(1,0,0,1));
+ m->addvert(m, v);
+ v.p = m->addposition(m, addpt3(center, e->by));
+ v.c = m->addcolor(m, Pt3(0,1,0,1));
+ m->addvert(m, v);
+ v.p = m->addposition(m, addpt3(center, e->bz));
+ v.c = m->addcolor(m, Pt3(0,0,1,1));
+ m->addvert(m, v);
- m->addprim(m, prims[0]);
- m->addprim(m, prims[1]);
- m->addprim(m, prims[2]);
+ l = mkprim(PLine);
+ l.v[0] = 0;
+ for(i = 0; i < 3; i++){
+ l.v[1] = i+1;
+ m->addprim(m, l);
+ }
s->addent(s, e);
}
@@ -488,9 +524,13 @@
static Quaternion orient = {1,0,0,0};
Quaternion Δorient;
Point3 p, cp0, cp1, cv;
+ Primitive *prim, *lastprim;
+ Vertex *v;
double cr;
- int i, j;
+ int i, cidx;
+ cidx = -1;
+
switch(opmode){
case OMOrbit:
if((om.buttons^mctl->buttons) != 0)
@@ -524,10 +564,16 @@
cv = viewport2world(cam, Pt3(mctl->xy.x+10, mctl->xy.y, 1, 1));
cr = vec3len(subpt3(cv, cp0)) * cam->clip.f/cam->clip.n;
- for(i = 0; i < model->nprims; i++)
- for(j = 0; j < model->prims[i].type+1; j++){
- if(ptincone(model->prims[i].v[j].p, cam->p, cp1, cr))
- model->prims[i].v[j].c = Pt3(0.5,0.5,0,1);
+ if(cidx < 0)
+ cidx = model->addcolor(model, Pt3(0.5,0.5,0,1));
+
+ lastprim = itemarrayget(model->prims, model->prims->nitems-1);
+ for(prim = model->prims->items; prim <= lastprim; prim++)
+ for(i = 0; i < prim->type+1; i++){
+ v = itemarrayget(model->verts, prim->v[i]);
+ p = *(Point3*)itemarrayget(model->positions, v->p);
+ if(ptincone(p, cam->p, cp1, cr))
+ v->c = cidx;
}
break;
}
@@ -573,7 +619,7 @@
usrlog->send(usrlog, "create: %r");
break;
}
- writemodel(fd, model, 1);
+ writemodel(fd, model);
close(fd);
break;
case QUIT:
--- a/obj.c
+++ b/obj.c
@@ -8,6 +8,18 @@
#include "fns.h"
#include "libobj/obj.h"
+static Point3
+VGP3(OBJVertex v)
+{
+ return Pt3(v.x, v.y, v.z, 1);
+}
+
+static Point2
+VGP2(OBJVertex v)
+{
+ return Pt2(v.x, v.y, 1);
+}
+
/*
* fan triangulation.
*
@@ -121,8 +133,9 @@
static int
loadobjmodel(Model *m, OBJ *obj)
{
- Primitive *p;
- OBJVertex *pverts, *tverts, *nverts, *v; /* geometric, texture and normals vertices */
+ Primitive prim;
+ Vertex v, *vp;
+ OBJVertex *pverts, *tverts, *nverts; /* geometric, texture and normals vertices */
OBJElem **trielems, *e, *ne;
OBJObject *o;
OBJIndexArray *idxtab;
@@ -129,8 +142,8 @@
OBJ2MtlMap mtlmap;
OBJMaterial *objmtl;
Material *mtl;
- Point3 n; /* surface normal */
- int i, idx, nt, maxnt, neednormal, gottaclean;
+ int i, idx, nt, maxnt, hastexcoords, neednormal, gottaclean;
+ int defcolidx, nidx; /* default color and normal indices */
pverts = obj->vertdata[OBJVGeometric].verts;
tverts = obj->vertdata[OBJVTexture].verts;
@@ -175,6 +188,14 @@
addmtlmap(&mtlmap, objmtl, m->nmaterials-1);
}
+ for(i = 0; i < obj->vertdata[OBJVGeometric].nvert; i++)
+ m->addposition(m, VGP3(pverts[i]));
+ for(i = 0; i < obj->vertdata[OBJVNormal].nvert; i++)
+ m->addnormal(m, VGP3(nverts[i]));
+ for(i = 0; i < obj->vertdata[OBJVTexture].nvert; i++)
+ m->addtexcoord(m, VGP2(tverts[i]));
+ defcolidx = m->addcolor(m, Pt3(1,1,1,1));
+
for(i = 0; i < nelem(obj->objtab); i++)
for(o = obj->objtab[i]; o != nil; o = o->next)
for(e = o->child; e != nil; e = ne){
@@ -182,42 +203,37 @@
switch(e->type){
case OBJEPoint:
- m->prims = erealloc(m->prims, ++m->nprims*sizeof(*m->prims));
- p = &m->prims[m->nprims-1];
- memset(p, 0, sizeof *p);
- p->type = PPoint;
- p->mtl = getmtlmap(&mtlmap, e->mtl);
+ prim = mkprim(PPoint);
+ prim.mtl = getmtlmap(&mtlmap, e->mtl);
+ v = mkvert();
idxtab = &e->indextab[OBJVGeometric];
- v = &pverts[idxtab->indices[0]];
- p->v[0].p = Pt3(v->x, v->y, v->z, v->w);
- p->v[0].c = Pt3(1,1,1,1);
+ v.p = idxtab->indices[0];
+ v.c = defcolidx;
idxtab = &e->indextab[OBJVTexture];
- if(idxtab->nindex == 1){
- v = &tverts[idxtab->indices[0]];
- p->v[0].uv = Pt2(v->u, v->v, 1);
- }
+ if(idxtab->nindex == 1)
+ v.uv = idxtab->indices[0];
+
+ prim.v[0] = m->addvert(m, v);
+ m->addprim(m, prim);
break;
case OBJELine:
- m->prims = erealloc(m->prims, ++m->nprims*sizeof(*m->prims));
- p = &m->prims[m->nprims-1];
- memset(p, 0, sizeof *p);
- p->type = PLine;
- p->mtl = getmtlmap(&mtlmap, e->mtl);
+ prim = mkprim(PLine);
+ prim.mtl = getmtlmap(&mtlmap, e->mtl);
for(idx = 0; idx < 2; idx++){
+ v = mkvert();
idxtab = &e->indextab[OBJVGeometric];
- v = &pverts[idxtab->indices[idx]];
- p->v[idx].p = Pt3(v->x, v->y, v->z, v->w);
- p->v[idx].c = Pt3(1,1,1,1);
+ v.p = idxtab->indices[idx];
+ v.c = defcolidx;
idxtab = &e->indextab[OBJVTexture];
- if(idxtab->nindex == 2){
- v = &tverts[idxtab->indices[idx]];
- p->v[idx].uv = Pt2(v->u, v->v, 1);
- }
+ if(idxtab->nindex == 2)
+ v.uv = idxtab->indices[idx];
+ prim.v[idx] = m->addvert(m, v);
}
+ m->addprim(m, prim);
break;
case OBJEFace:
idxtab = &e->indextab[OBJVGeometric];
@@ -238,54 +254,78 @@
while(nt-- > 0){
e = trielems[nt];
+ hastexcoords = 0;
neednormal = 0;
- m->prims = erealloc(m->prims, ++m->nprims*sizeof(*m->prims));
- p = &m->prims[m->nprims-1];
- memset(p, 0, sizeof *p);
- p->type = PTriangle;
- p->mtl = getmtlmap(&mtlmap, e->mtl);
+ prim = mkprim(PTriangle);
+ prim.mtl = getmtlmap(&mtlmap, e->mtl);
for(idx = 0; idx < 3; idx++){
+ v = mkvert();
idxtab = &e->indextab[OBJVGeometric];
- v = &pverts[idxtab->indices[idx]];
- p->v[idx].p = Pt3(v->x, v->y, v->z, v->w);
- p->v[idx].c = Pt3(1,1,1,1);
+ v.p = idxtab->indices[idx];
+ v.c = defcolidx;
idxtab = &e->indextab[OBJVNormal];
- if(idxtab->nindex == 3){
- v = &nverts[idxtab->indices[idx]];
- p->v[idx].n = normvec3(Vec3(v->i, v->j, v->k));
- }else
+ if(idxtab->nindex == 3)
+ v.n = idxtab->indices[idx];
+ else
neednormal = 1;
idxtab = &e->indextab[OBJVTexture];
if(idxtab->nindex == 3){
- v = &tverts[idxtab->indices[idx]];
- p->v[idx].uv = Pt2(v->u, v->v, 1);
+ hastexcoords = 1;
+ v.uv = idxtab->indices[idx];
}
+ prim.v[idx] = m->addvert(m, v);
}
- if(p->v[0].uv.w != 0){
- Point3 e0, e1;
- Point2 Δuv0, Δuv1;
+
+ if(hastexcoords){
+ Point3 *p[3], e0, e1, tangent;
+ Point2 *uv[3], Δ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);
+ for(idx = 0; idx < 3; idx++){
+ vp = itemarrayget(m->verts, prim.v[idx]);
+ p[idx] = itemarrayget(m->positions, vp->p);
+ uv[idx] = itemarrayget(m->texcoords, vp->uv);
+ }
+ e0 = subpt3(*p[1], *p[0]);
+ e1 = subpt3(*p[2], *p[0]);
+ Δuv0 = subpt2(*uv[1], *uv[0]);
+ Δuv1 = subpt2(*uv[2], *uv[0]);
+
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);
+
+ tangent.x = det*(Δuv1.y * e0.x - Δuv0.y * e1.x);
+ tangent.y = det*(Δuv1.y * e0.y - Δuv0.y * e1.y);
+ tangent.z = det*(Δuv1.y * e0.z - Δuv0.y * e1.z);
+ tangent.w = 0;
+ tangent = normvec3(tangent);
+
+ prim.tangent = m->addtangent(m, tangent);
}
+
if(neednormal){
- n = normvec3(crossvec3(subpt3(p->v[1].p, p->v[0].p), subpt3(p->v[2].p, p->v[0].p)));
- p->v[0].n = p->v[1].n = p->v[2].n = n;
+ Point3 *p[3], n;
+
+ for(idx = 0; idx < 3; idx++){
+ vp = itemarrayget(m->verts, prim.v[idx]);
+ p[idx] = itemarrayget(m->positions, vp->p);
+ }
+
+ n = normvec3(crossvec3(subpt3(*p[1], *p[0]), subpt3(*p[2], *p[0])));
+ nidx = m->addnormal(m, n);
+ for(idx = 0; idx < 3; idx++){
+ vp = itemarrayget(m->verts, prim.v[idx]);
+ vp->n = nidx;
+ }
}
+
+ m->addprim(m, prim);
+
if(gottaclean){
free(e->indextab[OBJVGeometric].indices);
free(e->indextab[OBJVNormal].indices);
@@ -300,7 +340,7 @@
free(trielems);
clrmtlmap(&mtlmap);
- return m->nprims;
+ return m->prims->nitems;
}
static Model *
@@ -333,7 +373,7 @@
dedup = 1;
ARGBEGIN{
- case 'd': dedup--; break;
+ case 'd': dedup--; break; /* TODO waiting for a Model compaction routine */
default: usage();
}ARGEND;
if(argc > 2)
@@ -347,10 +387,10 @@
sysfatal("readobjmodel: %r");
if(dstdir == nil){
- if(writemodel(1, m, dedup) == 0)
+ if(writemodel(1, m) == 0)
sysfatal("writemodel: %r");
}else{
- if(exportmodel(dstdir, m, dedup) < 0)
+ if(exportmodel(dstdir, m) < 0)
sysfatal("exportmodel: %r");
}
--- a/plot3.c
+++ b/plot3.c
@@ -174,7 +174,8 @@
Model *mdl;
Entity *ent;
Primitive line, mark;
- Point3 stepv;
+ Vertex v;
+ Point3 stepv, p0, p1, mp0;
int i;
mdl = newmodel();
@@ -181,41 +182,59 @@
ent = newentity("axis scales", mdl);
theplot.scn->addent(theplot.scn, ent);
- line.type = PLine;
- line.v[0].c = line.v[1].c = Pt3(0.4,0.4,0.4,1);
+ line = mkprim(PLine);
+ v = mkvert();
+ v.c = mdl->addcolor(mdl, Pt3(0.4,0.4,0.4,1));
mark = line;
/* x scale */
- line.v[0].p = Pt3(smallestbbox(x), smallestbbox(y), smallestbbox(z), 1);
- line.v[1].p = Pt3(biggestbbox(x), smallestbbox(y), smallestbbox(z), 1);
+ v.p = mdl->addposition(mdl, Pt3(smallestbbox(x), smallestbbox(y), smallestbbox(z), 1));
+ line.v[0] = mdl->addvert(mdl, v);
+ v.p = mdl->addposition(mdl, Pt3(biggestbbox(x), smallestbbox(y), smallestbbox(z), 1));
+ line.v[1] = mdl->addvert(mdl, v);
mdl->addprim(mdl, line);
- stepv = subpt3(line.v[1].p, line.v[0].p);
+ p0 = *(Point3*)itemarrayget(mdl->positions, v.p - 1);
+ p1 = *(Point3*)itemarrayget(mdl->positions, v.p);
+ stepv = subpt3(p1, p0);
stepv = divpt3(stepv, 10);
for(i = 1; i <= 10; i++){
- mark.v[0].p = addpt3(line.v[0].p, mulpt3(stepv, i));
- mark.v[1].p = addpt3(mark.v[0].p, qrotate(stepv, Vec3(0,1,0), 90*DEG));
+ mp0 = addpt3(p0, mulpt3(stepv, i));
+ v.p = mdl->addposition(mdl, mp0);
+ mark.v[0] = mdl->addvert(mdl, v);
+ v.p = mdl->addposition(mdl, addpt3(mp0, qrotate(stepv, Vec3(0,1,0), 90*DEG)));
+ mark.v[1] = mdl->addvert(mdl, v);
mdl->addprim(mdl, mark);
}
/* y scale */
- line.v[1].p = Pt3(smallestbbox(x), biggestbbox(y), smallestbbox(z), 1);
+ v.p = mdl->addposition(mdl, Pt3(smallestbbox(x), biggestbbox(y), smallestbbox(z), 1));
+ line.v[1] = mdl->addvert(mdl, v);
mdl->addprim(mdl, line);
- stepv = subpt3(line.v[1].p, line.v[0].p);
+ p1 = *(Point3*)itemarrayget(mdl->positions, v.p);
+ stepv = subpt3(p1, p0);
stepv = divpt3(stepv, 10);
for(i = 1; i <= 10; i++){
- mark.v[0].p = addpt3(line.v[0].p, mulpt3(stepv, i));
- mark.v[1].p = addpt3(mark.v[0].p, qrotate(stepv, normvec3(Vec3(-1,0,1)), 90*DEG));
+ mp0 = addpt3(p0, mulpt3(stepv, i));
+ v.p = mdl->addposition(mdl, mp0);
+ mark.v[0] = mdl->addvert(mdl, v);
+ v.p = mdl->addposition(mdl, addpt3(mp0, qrotate(stepv, normvec3(Vec3(-1,0,1)), 90*DEG)));
+ mark.v[1] = mdl->addvert(mdl, v);
mdl->addprim(mdl, mark);
}
/* z scale */
- line.v[1].p = Pt3(smallestbbox(x), smallestbbox(y), biggestbbox(z), 1);
+ v.p = mdl->addposition(mdl, Pt3(smallestbbox(x), smallestbbox(y), biggestbbox(z), 1));
+ line.v[1] = mdl->addvert(mdl, v);
mdl->addprim(mdl, line);
- stepv = subpt3(line.v[1].p, line.v[0].p);
+ p1 = *(Point3*)itemarrayget(mdl->positions, v.p);
+ stepv = subpt3(p1, p0);
stepv = divpt3(stepv, 10);
for(i = 1; i <= 10; i++){
- mark.v[0].p = addpt3(line.v[0].p, mulpt3(stepv, i));
- mark.v[1].p = addpt3(mark.v[0].p, qrotate(stepv, Vec3(0,1,0), -90*DEG));
+ mp0 = addpt3(p0, mulpt3(stepv, i));
+ v.p = mdl->addposition(mdl, mp0);
+ mark.v[0] = mdl->addvert(mdl, v);
+ v.p = mdl->addposition(mdl, addpt3(mp0, qrotate(stepv, Vec3(0,1,0), -90*DEG)));
+ mark.v[1] = mdl->addvert(mdl, v);
mdl->addprim(mdl, mark);
}
}
@@ -227,6 +246,8 @@
Entity *ent;
Scene *scn;
Primitive prim;
+ Vertex v;
+ static Color prevcol;
Plotpt *p;
mdl = newmodel();
@@ -235,11 +256,15 @@
scn->addent(scn, ent);
theplot.scn = scn;
- memset(&prim, 0, sizeof prim);
- prim.type = PPoint;
+ prim = mkprim(PPoint);
+ v = mkvert();
for(p = theplot.pts; p < theplot.pts + theplot.npts; p++){
- prim.v[0].p = p->p;
- prim.v[0].c = p->c->c;
+ v.p = mdl->addposition(mdl, p->p);
+ if(!eqpt3(prevcol, p->c->c)){
+ v.c = mdl->addcolor(mdl, p->c->c);
+ prevcol = p->c->c;
+ }
+ prim.v[0] = mdl->addvert(mdl, v);
mdl->addprim(mdl, prim);
}
free(theplot.pts);
--- a/procgen.c
+++ b/procgen.c
@@ -147,6 +147,7 @@
{
Memimage *out;
Point dim;
+ Vertex v;
int skip;
double time;
@@ -181,13 +182,17 @@
cam = Cam(out->r, rctl, ORTHOGRAPHIC, 40*DEG, 1, 10);
placecamera(cam, scn, Pt3(0,0,0,1), Vec3(0,0,-1), Vec3(0,1,0));
- quad[0].type = quad[1].type = PTriangle;
- quad[0].v[0].p = vcs2clip(cam, viewport2vcs(cam, Pt3(out->r.min.x, out->r.max.y, 1, 1)));
- quad[0].v[1].p = vcs2clip(cam, viewport2vcs(cam, Pt3(out->r.max.x, out->r.min.y, 1, 1)));
- quad[0].v[2].p = vcs2clip(cam, viewport2vcs(cam, Pt3(out->r.min.x, out->r.min.y, 1, 1)));
- quad[1].v[0].p = quad[0].v[0].p;
- quad[1].v[1].p = vcs2clip(cam, viewport2vcs(cam, Pt3(out->r.max.x, out->r.max.y, 1, 1)));
- quad[1].v[2].p = quad[0].v[1].p;
+ quad[0] = quad[1] = mkprim(PTriangle);
+ v.p = mdl->addposition(mdl, vcs2clip(cam, viewport2vcs(cam, Pt3(out->r.min.x, out->r.max.y, 1, 1))));
+ quad[0].v[0] = mdl->addvert(mdl, v);
+ v.p = mdl->addposition(mdl, vcs2clip(cam, viewport2vcs(cam, Pt3(out->r.max.x, out->r.min.y, 1, 1))));
+ quad[0].v[1] = mdl->addvert(mdl, v);
+ v.p = mdl->addposition(mdl, vcs2clip(cam, viewport2vcs(cam, Pt3(out->r.min.x, out->r.min.y, 1, 1))));
+ quad[0].v[2] = mdl->addvert(mdl, v);
+ quad[1].v[0] = quad[0].v[0];
+ v.p = mdl->addposition(mdl, vcs2clip(cam, viewport2vcs(cam, Pt3(out->r.max.x, out->r.max.y, 1, 1))));
+ quad[1].v[1] = mdl->addvert(mdl, v);
+ quad[1].v[2] = quad[0].v[1];
mdl->addprim(mdl, quad[0]);
mdl->addprim(mdl, quad[1]);
scn->addent(scn, ent);
--- a/solar.c
+++ b/solar.c
@@ -283,7 +283,9 @@
Entity *e, *esel;
Model *msel;
Primitive l;
- int i, j;
+ Vertex v;
+ Point3 *pt, *lastpt;
+ int i;
if(p == oldp)
return;
@@ -291,8 +293,10 @@
qlock(&scenelk);
oldp = selplanet = p;
esel = scene->getent(scene, "selection");
- if(esel != nil)
+ if(esel != nil){
scene->delent(scene, esel);
+ delentity(esel);
+ }
qunlock(&scenelk);
lockdisplay(display);
@@ -314,43 +318,47 @@
unlockdisplay(display);
memset(&aabb, 0, sizeof aabb);
- for(i = 0; i < e->mdl->nprims; i++)
- for(j = 0; j < e->mdl->prims[i].type+1; j++){
- aabb.min = minpt3(aabb.min, e->mdl->prims[i].v[j].p);
- aabb.max = maxpt3(aabb.max, e->mdl->prims[i].v[j].p);
- }
+ pt = e->mdl->positions->items;
+ for(lastpt = pt + e->mdl->positions->nitems; pt < lastpt; pt++){
+ aabb.min = minpt3(aabb.min, *pt);
+ aabb.max = maxpt3(aabb.max, *pt);
+ }
aabb.min = mulpt3(aabb.min, p->scale*0.8);
aabb.max = mulpt3(aabb.max, p->scale*0.8);
aabb.min.w = aabb.max.w = 1;
- memset(&l, 0, sizeof l);
- l.type = PLine;
- l.v[0].c = l.v[1].c = Pt3(0.2666, 0.5333, 0.2666, 1);
+ l = mkprim(PLine);
+ v = mkvert();
+ v.c = msel->addcolor(msel, Pt3(0.2666, 0.5333, 0.2666, 1));
+
+ for(i = 0; i < 4; i++){
+ v.p = msel->addposition(msel, aabb.min);
+ msel->addvert(msel, v);
+ aabb.min = qrotate(aabb.min, Vec3(0,1,0), PI/2);
+ }
+ aabb.max = qrotate(aabb.max, Vec3(0,1,0), PI);
+ for(i = 0; i < 4; i++){
+ v.p = msel->addposition(msel, aabb.max);
+ msel->addvert(msel, v);
+ aabb.max = qrotate(aabb.max, Vec3(0,1,0), PI/2);
+ }
+
/* bottom */
- l.v[0].p = aabb.min;
- l.v[1].p = qrotate(aabb.min, Vec3(0,1,0), PI/2);
- msel->addprim(msel, l);
- for(i = 0; i < 3; i++){
- l.v[0].p = l.v[1].p;
- l.v[1].p = qrotate(l.v[1].p, Vec3(0,1,0), PI/2);
+ for(i = 1; i <= 4; i++){
+ l.v[0] = i-1;
+ l.v[1] = i%4;
msel->addprim(msel, l);
}
/* top */
- l.v[0].p = aabb.max;
- l.v[1].p = qrotate(aabb.max, Vec3(0,1,0), PI/2);
- msel->addprim(msel, l);
- for(i = 0; i < 3; i++){
- l.v[0].p = l.v[1].p;
- l.v[1].p = qrotate(l.v[1].p, Vec3(0,1,0), PI/2);
+ for(i = 4+1; i <= 4+4; i++){
+ l.v[0] = i-1;
+ l.v[1] = i%4 + 4;
msel->addprim(msel, l);
}
/* struts */
- l.v[0].p = aabb.min;
- l.v[1].p = qrotate(aabb.max, Vec3(0,1,0), PI);
- msel->addprim(msel, l);
- for(i = 0; i < 3; i++){
- l.v[0].p = qrotate(l.v[0].p, Vec3(0,1,0), PI/2);
- l.v[1].p = qrotate(l.v[1].p, Vec3(0,1,0), PI/2);
+ for(i = 0; i < 4; i++){
+ l.v[0] = i;
+ l.v[1] = i+4;
msel->addprim(msel, l);
}
@@ -886,6 +894,7 @@
Channel *keyc;
Entity *subject;
Model *model;
+ Point3 *p, *lastp;
Point lblsiz;
int fd, i, j;
@@ -913,11 +922,11 @@
* normalize the vertices so that we can scale
* each planet based on its radius
*/
- for(i = 0; i < model->nprims; i++)
- for(j = 0; j < model->prims[i].type+1; j++){
- model->prims[i].v[j].p = normvec3(model->prims[i].v[j].p);
- model->prims[i].v[j].p.w = 1;
- }
+ p = model->positions->items;
+ for(lastp = p + model->positions->nitems; p < lastp; p++){
+ *p = normvec3(*p);
+ p->w = 1;
+ }
scene = newscene(nil);
for(i = 0; i < nelem(planets); i++){
subject = newentity(planets[i].name, model);
--- a/stl.c
+++ b/stl.c
@@ -11,24 +11,26 @@
static int
loadstlmodel(Model *m, Stl *stl)
{
- Primitive p;
+ Primitive prim;
+ Vertex v;
Stltri **tri;
+ int i;
- memset(&p, 0, sizeof p);
- p.type = PTriangle;
- p.v[0].c = p.v[1].c = p.v[2].c = Pt3(1,1,1,1);
+ prim = mkprim(PTriangle);
+ v = mkvert();
+ v.c = m->addcolor(m, Pt3(1,1,1,1));
for(tri = stl->tris; tri < stl->tris+stl->ntris; tri++){
- p.v[0].p = Pt3((*tri)->v[0][0], (*tri)->v[0][1], (*tri)->v[0][2], 1);
- p.v[1].p = Pt3((*tri)->v[1][0], (*tri)->v[1][1], (*tri)->v[1][2], 1);
- p.v[2].p = Pt3((*tri)->v[2][0], (*tri)->v[2][1], (*tri)->v[2][2], 1);
- p.v[0].n = Vec3((*tri)->n[0], (*tri)->n[1], (*tri)->n[2]);
- p.v[1].n = p.v[2].n = p.v[0].n;
+ v.n = m->addnormal(m, Vec3((*tri)->n[0], (*tri)->n[1], (*tri)->n[2]));
+ for(i = 0; i < 3; i++){
+ v.p = m->addposition(m, Pt3((*tri)->v[i][0], (*tri)->v[i][1], (*tri)->v[i][2], 1));
+ prim.v[i] = m->addvert(m, v);
+ }
- m->addprim(m, p);
+ m->addprim(m, prim);
}
- return m->nprims;
+ return m->prims->nitems;
}
static Model *
@@ -62,7 +64,7 @@
dedup = 1;
infile = "/fd/0";
ARGBEGIN{
- case 'd': dedup--; break;
+ case 'd': dedup--; break; /* TODO waiting for a Model compaction routine */
default: usage();
}ARGEND;
if(argc == 1)
@@ -78,7 +80,7 @@
if(m == nil)
sysfatal("readstlmodel: %r");
- if(writemodel(1, m, dedup) == 0)
+ if(writemodel(1, m) == 0)
sysfatal("writemodel: %r");
exits(nil);
--- a/toobj.c
+++ b/toobj.c
@@ -10,26 +10,26 @@
#include "libobj/obj.h"
static OBJVertex
-GP2V(Point2 p)
+GP2V(Point2 *p)
{
OBJVertex v;
- v.x = p.x;
- v.y = p.y;
- v.z = p.w;
+ v.x = p->x;
+ v.y = p->y;
+ v.z = p->w;
v.w = 0;
return v;
}
static OBJVertex
-GP3V(Point3 p)
+GP3V(Point3 *p)
{
OBJVertex v;
- v.x = p.x;
- v.y = p.y;
- v.z = p.z;
- v.w = p.w;
+ v.x = p->x;
+ v.y = p->y;
+ v.z = p->z;
+ v.w = p->w;
return v;
}
@@ -36,13 +36,13 @@
static int
loadobjmodel(OBJ *obj, Model *m)
{
- Primitive *prim;
- OBJVertex v;
+ Primitive *prim, *lastprim;
+ Vertex *v;
OBJElem *e;
OBJObject *o;
OBJMaterial *objmtl;
Material *mtl;
- int i, idx;
+ int i;
if(m->nmaterials > 0)
obj->materials = objallocmtl("main.mtl");
@@ -85,9 +85,17 @@
objaddmtl(obj->materials, objmtl);
}
+ for(i = 0; i < m->positions->nitems; i++)
+ objaddvertex(obj, GP3V(itemarrayget(m->positions, i)), OBJVGeometric);
+ for(i = 0; i < m->normals->nitems; i++)
+ objaddvertex(obj, GP3V(itemarrayget(m->normals, i)), OBJVNormal);
+ for(i = 0; i < m->texcoords->nitems; i++)
+ objaddvertex(obj, GP3V(itemarrayget(m->texcoords, i)), OBJVTexture);
+
o = objallocobject("default");
objpushobject(obj, o);
- for(prim = m->prims; prim < m->prims + m->nprims; prim++){
+ lastprim = itemarrayget(m->prims, m->prims->nitems-1);
+ for(prim = m->prims->items; prim <= lastprim; prim++){
/*
* XXX A Model doesn't have the indexed attribute
* structure an OBJ has, so this conversion is very
@@ -108,21 +116,12 @@
}
for(i = 0; i < prim->type+1; i++){
- v = GP3V(prim->v[i].p);
- idx = objaddvertex(obj, v, OBJVGeometric);
- objaddelemidx(e, OBJVGeometric, idx);
-
- if(memcmp(&prim->v[i].n, &ZP3, sizeof(Point3)) != 0){
- v = GP3V(prim->v[i].n);
- idx = objaddvertex(obj, v, OBJVNormal);
- objaddelemidx(e, OBJVNormal, idx);
- }
-
- if(memcmp(&prim->v[i].uv, &ZP2, sizeof(Point2)) != 0){
- v = GP2V(prim->v[i].uv);
- idx = objaddvertex(obj, v, OBJVTexture);
- objaddelemidx(e, OBJVTexture, idx);
- }
+ v = itemarrayget(m->verts, prim->v[i]);
+ objaddelemidx(e, OBJVGeometric, v->p);
+ if(v->n != NaI)
+ objaddelemidx(e, OBJVNormal, v->n);
+ if(v->uv != NaI)
+ objaddelemidx(e, OBJVTexture, v->uv);
}
if(prim->mtl != nil)
@@ -130,7 +129,7 @@
objaddelem(o, e);
}
- return m->nprims;
+ return m->prims->nitems;
}
static void
--- a/tostl.c
+++ b/tostl.c
@@ -11,7 +11,9 @@
static int
loadstlmodel(Stl *stl, Model *m)
{
- Primitive *p;
+ Primitive *prim, *lastprim;
+ Vertex *v;
+ Point3 *p;
Stltri **tri, *t;
int i;
@@ -18,7 +20,7 @@
snprint((char*)stl->hdr, sizeof(stl->hdr), "Exported with libstl from ⑨");
/* XXX we assume all prims are triangles */
- stl->ntris = m->nprims;
+ stl->ntris = m->prims->nitems;
stl->tris = emalloc(stl->ntris*sizeof(Stltri*));
/* since we don't use attributes we can allocate tris in bulk */
@@ -28,20 +30,26 @@
*tri = &t[tri - stl->tris];
tri = stl->tris;
- for(p = m->prims; p < m->prims+m->nprims; p++){
- if(p->type != PTriangle){
+ lastprim = itemarrayget(m->prims, m->prims->nitems-1);
+ for(prim = m->prims->items; prim <= lastprim; prim++){
+ if(prim->type != PTriangle){
stl->ntris--;
continue;
}
- (*tri)->n[0] = p->v[0].n.x;
- (*tri)->n[1] = p->v[0].n.y;
- (*tri)->n[2] = p->v[0].n.z;
+ v = itemarrayget(m->verts, prim->v[0]);
+ p = itemarrayget(m->normals, v->n);
+ (*tri)->n[0] = p->x;
+ (*tri)->n[1] = p->y;
+ (*tri)->n[2] = p->z;
+
for(i = 0; i < 3; i++){
- (*tri)->v[i][0] = p->v[i].p.x;
- (*tri)->v[i][1] = p->v[i].p.y;
- (*tri)->v[i][2] = p->v[i].p.z;
+ v = itemarrayget(m->verts, prim->v[i]);
+ p = itemarrayget(m->positions, v->p);
+ (*tri)->v[i][0] = p->x;
+ (*tri)->v[i][1] = p->y;
+ (*tri)->v[i][2] = p->z;
}
tri++;
}
--- a/vis.c
+++ b/vis.c
@@ -194,20 +194,25 @@
{
static int inited;
Model *m;
- Primitive *prim;
+ Primitive *prim, *lastprim;
Vertex *v;
+ Point3 *p;
+ int i;
m = e->mdl;
- for(prim = m->prims; prim < m->prims + m->nprims; prim++)
- for(v = prim->v; v < prim->v + prim->type+1; v++){
+ lastprim = itemarrayget(m->prims, m->prims->nitems-1);
+ for(prim = m->prims->items; prim <= lastprim; prim++)
+ for(i = 0; i < prim->type+1; i++){
+ v = itemarrayget(m->verts, prim->v[i]);
+ p = itemarrayget(m->positions, v->p);
if(!inited){
- scenebbox.min = scenebbox.max = addpt3(e->p, v->p);
+ scenebbox.min = scenebbox.max = addpt3(e->p, *p);
inited++;
continue;
}
- scenebbox.min = minpt3(scenebbox.min, addpt3(e->p, v->p));
- scenebbox.max = maxpt3(scenebbox.max, addpt3(e->p, v->p));
+ scenebbox.min = minpt3(scenebbox.min, addpt3(e->p, *p));
+ scenebbox.max = maxpt3(scenebbox.max, addpt3(e->p, *p));
}
scenebbox.c = divpt3(addpt3(scenebbox.max, scenebbox.min), 2);
scenebbox.r = max(vec3len(scenebbox.min), vec3len(scenebbox.max));
@@ -259,7 +264,7 @@
renderproc(void *)
{
Material *mtl;
- Primitive *prim;
+ Primitive *prim, *lastprim;
uvlong t0, Δt;
int fd;
double time;
@@ -267,6 +272,7 @@
threadsetname("renderproc");
fd = -1;
+ mtl = nil;
if(inception){
fd = open("/dev/screen", OREAD);
if(fd < 0)
@@ -278,7 +284,8 @@
model->addmaterial(model, *mtl);
free(mtl);
mtl = &model->materials[model->nmaterials-1];
- for(prim = model->prims; prim < model->prims+model->nprims; prim++)
+ lastprim = itemarrayget(model->prims, model->prims->nitems-1);
+ for(prim = model->prims->items; prim <= lastprim; prim++)
prim->mtl = mtl;
}
@@ -663,45 +670,40 @@
mkblendtestscene(void)
{
static Color cols[] = {{1,0,0,0.5}, {0,1,0,0.5}, {0,0,1,0.5}};
+ static Point3 Yaxis = {0,1,0,0};
Entity *ent;
- Model *mdl;
Primitive t[2];
- Point3 p, v1, v2;
- int i, j, k;
+ Vertex v;
+ Point3 p, n;
+ int i, j;
- memset(t, 0, sizeof t);
- t[0].type = t[1].type = PTriangle;
+ t[0] = t[1] = mkprim(PTriangle);
+ v = mkvert();
- /* build the first face/quad, facing the positive z axis */
- p = Vec3(-0.5,-0.5,0);
- 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[0].v[0].n = t[0].v[1].n = t[0].v[2].n = Vec3(0,0,1);
- 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));
- t[1].v[2].n = Vec3(0,0,1);
+ model = newmodel();
+ ent = newentity(nil, model);
+ scene->addent(scene, ent);
+ p = Pt3(-0.5,-0.5,0,1);
+ n = Vec3(0,0,1);
for(i = 0; i < nelem(cols); 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, Vec3(0,1,0), PI/nelem(cols));
- t[j].v[k].n = qrotate(t[j].v[k].n, Vec3(0,1,0), PI/nelem(cols));
- }
- t[j].v[k].c = cols[i];
- }
+ v.c = model->addcolor(model, cols[i]);
+ v.n = model->addnormal(model, n);
+ for(j = 0; j < 4; j++){
+ v.p = model->addposition(model, p);
+ model->addvert(model, v);
+ p = qrotate(p, n, PI/2);
+ }
- mdl = newmodel();
- mdl->addprim(mdl, t[0]);
- mdl->addprim(mdl, t[1]);
- ent = newentity(nil, mdl);
- scene->addent(scene, ent);
- updatebbox(ent);
+ t[0].v[0] = v.p-3 + 0; t[0].v[1] = v.p-3 + 1; t[0].v[2] = v.p-3 + 2;
+ t[1].v[0] = v.p-3 + 0; t[1].v[1] = v.p-3 + 2; t[1].v[2] = v.p-3 + 3;
+ model->addprim(model, t[0]);
+ model->addprim(model, t[1]);
+
+ p = qrotate(p, Yaxis, PI/nelem(cols));
+ n = qrotate(n, Yaxis, PI/nelem(cols));
}
+ updatebbox(ent);
}
void
@@ -749,7 +751,7 @@
Channel *keyc;
Entity *subject;
Material *tmpmtl;
- Primitive *prim;
+ Primitive *prim, *lastprim;
char *texpath, *mdlpath, *s;
int i, fd, fbw, fbh, scale;
@@ -799,7 +801,7 @@
scene->addent(scene, subject);
updatebbox(subject);
-fprint(2, "%s: %lud prims\n", mdlpath, model->nprims);
+fprint(2, "%s: %llud prims\n", mdlpath, model->prims->nitems);
if(argc == 0 && texpath != nil){
fd = open(texpath, OREAD);
@@ -813,7 +815,8 @@
model->addmaterial(model, *tmpmtl);
free(tmpmtl);
tmpmtl = &model->materials[model->nmaterials-1];
- for(prim = model->prims; prim < model->prims+model->nprims; prim++)
+ lastprim = itemarrayget(model->prims, model->prims->nitems-1);
+ for(prim = model->prims->items; prim <= lastprim; prim++)
prim->mtl = tmpmtl;
}
}
--
⑨