ref: 88b8681339b85e27e3d1d98c867ac3aa0557f780
parent: 32360e2b88f88f643be632941580c90d3e466076
author: rodri <rgl@antares-labs.eu>
date: Sun Jan 14 17:14:04 EST 2024
triangulate quads. replace matrix rotation with quaternions. generalize texture image decoding. change lighting.
--- a/fns.h
+++ b/fns.h
@@ -27,4 +27,5 @@
void swap(int*, int*);
void memsetd(double*, double, usize);
Memimage *readtga(char*);
+Memimage *readpng(char*);
Memimage *rgb(ulong);
--- a/main.c
+++ b/main.c
@@ -22,7 +22,7 @@
int shownormals; /* XXX DBG */
char winspec[32];
-Point3 light = {0,-1,1,1}; /* global directional light */
+Point3 light = {0,1,1,1}; /* global directional light */
Point3 camera = {0,0,3,1};
Point3 center = {0,0,0,1};
Point3 up = {0,1,0,0};
@@ -174,12 +174,7 @@
Point3
vertshader(VSparams *sp)
{
- Matrix3 yrot = {
- cos(θ+fmod(ω*sp->su->uni_time/1e9, 2*PI)), 0, -sin(θ+fmod(ω*sp->su->uni_time/1e9, 2*PI)), 0,
- 0, 1, 0, 0,
- sin(θ+fmod(ω*sp->su->uni_time/1e9, 2*PI)), 0, cos(θ+fmod(ω*sp->su->uni_time/1e9, 2*PI)), 0,
- 0, 0, 0, 1,
- }, S = {
+ Matrix3 S = {
scale, 0, 0, 0,
0, scale, 0, 0,
0, 0, scale, 0,
@@ -188,14 +183,15 @@
identity3(M);
identity3(V);
- mulm3(yrot, S);
mulm3(M, rota);
- mulm3(M, yrot);
+ mulm3(M, S);
mulm3(V, view);
mulm3(V, M);
- *sp->n = xform3(*sp->n, M);
+ *sp->n = qrotate(*sp->n, Vec3(0,1,0), θ+fmod(ω*sp->su->uni_time/1e9, 2*PI));
sp->su->var_intensity[sp->idx] = fmax(0, dotvec3(*sp->n, light));
+ *sp->n = xform3(*sp->n, M);
+ *sp->p = qrotate(*sp->p, Vec3(0,1,0), θ+fmod(ω*sp->su->uni_time/1e9, 2*PI));
*sp->p = xform3(*sp->p, V);
return *sp->p;
}
@@ -407,10 +403,66 @@
for(e = o->child; e != nil; e = e->next){
idxtab = &e->indextab[OBJVGeometric];
/* discard non-triangles */
- if(e->type != OBJEFace || idxtab->nindex != 3)
+ if(e->type != OBJEFace || (idxtab->nindex != 3 && idxtab->nindex != 4))
continue;
- elems = erealloc(elems, ++nelems*sizeof(*elems));
- elems[nelems-1] = e;
+ if(idxtab->nindex == 4){ /* triangulate */
+ OBJElem *auxe;
+ OBJIndexArray *auxia;
+
+ auxe = emalloc(sizeof *auxe);
+ auxe->type = OBJEFace;
+ auxia = &auxe->indextab[OBJVGeometric];
+ auxia->nindex = 3;
+ auxia->indices = emalloc(auxia->nindex*sizeof(*auxia->indices));
+ auxia->indices[0] = idxtab->indices[0];
+ auxia->indices[1] = idxtab->indices[1];
+ auxia->indices[2] = idxtab->indices[2];
+ idxtab = &e->indextab[OBJVTexture];
+ auxia = &auxe->indextab[OBJVTexture];
+ auxia->nindex = 3;
+ auxia->indices = emalloc(auxia->nindex*sizeof(*auxia->indices));
+ auxia->indices[0] = idxtab->indices[0];
+ auxia->indices[1] = idxtab->indices[1];
+ auxia->indices[2] = idxtab->indices[2];
+ idxtab = &e->indextab[OBJVNormal];
+ auxia = &auxe->indextab[OBJVNormal];
+ auxia->nindex = 3;
+ auxia->indices = emalloc(auxia->nindex*sizeof(*auxia->indices));
+ auxia->indices[0] = idxtab->indices[0];
+ auxia->indices[1] = idxtab->indices[1];
+ auxia->indices[2] = idxtab->indices[2];
+ elems = erealloc(elems, ++nelems*sizeof(*elems));
+ elems[nelems-1] = auxe;
+
+ idxtab = &e->indextab[OBJVGeometric];
+ auxe = emalloc(sizeof *auxe);
+ auxe->type = OBJEFace;
+ auxia = &auxe->indextab[OBJVGeometric];
+ auxia->nindex = 3;
+ auxia->indices = emalloc(auxia->nindex*sizeof(*auxia->indices));
+ auxia->indices[0] = idxtab->indices[0];
+ auxia->indices[1] = idxtab->indices[2];
+ auxia->indices[2] = idxtab->indices[3];
+ idxtab = &e->indextab[OBJVTexture];
+ auxia = &auxe->indextab[OBJVTexture];
+ auxia->nindex = 3;
+ auxia->indices = emalloc(auxia->nindex*sizeof(*auxia->indices));
+ auxia->indices[0] = idxtab->indices[0];
+ auxia->indices[1] = idxtab->indices[2];
+ auxia->indices[2] = idxtab->indices[3];
+ idxtab = &e->indextab[OBJVNormal];
+ auxia = &auxe->indextab[OBJVNormal];
+ auxia->nindex = 3;
+ auxia->indices = emalloc(auxia->nindex*sizeof(*auxia->indices));
+ auxia->indices[0] = idxtab->indices[0];
+ auxia->indices[1] = idxtab->indices[2];
+ auxia->indices[2] = idxtab->indices[3];
+ elems = erealloc(elems, ++nelems*sizeof(*elems));
+ elems[nelems-1] = auxe;
+ }else{
+ elems = erealloc(elems, ++nelems*sizeof(*elems));
+ elems[nelems-1] = e;
+ }
}
if(nelems < nprocs){
nworkers = nelems;
@@ -760,7 +812,7 @@
Keyboardctl *kc;
Rune r;
Shader *s;
- char *mdlpath, *texpath;
+ char *mdlpath, *texpath, *p;
char *sname;
int fbw, fbh;
@@ -810,8 +862,17 @@
if((model = objparse(mdlpath)) == nil)
sysfatal("objparse: %r");
- if(texpath != nil && (modeltex = readtga(texpath)) == nil)
- sysfatal("readtga: %r");
+ if(texpath != nil){
+ if((p = strrchr(texpath, '\\')) == nil)
+ p = texpath;
+ p = strchr(p, '.');
+ if(p == nil)
+ sysfatal("unknown image file");
+ if(strcmp(++p, "tga") == 0 && (modeltex = readtga(texpath)) == nil)
+ sysfatal("readtga: %r");
+ else if(strcmp(p, "png") == 0 && (modeltex = readpng(texpath)) == nil)
+ sysfatal("readpng: %r");
+ }
{
int i, nv[OBJNVERT], nf;
--- a/util.c
+++ b/util.c
@@ -53,43 +53,66 @@
*dp = v;
}
+typedef struct Deco Deco;
+struct Deco
+{
+ int pfd[2];
+ int infd;
+ char *prog;
+};
+
static void
decproc(void *arg)
{
- int fd, *pfd;
+ char buf[32];
+ Deco *d;
- pfd = arg;
- fd = pfd[2];
+ d = arg;
- close(pfd[0]);
- dup(fd, 0);
- close(fd);
- dup(pfd[1], 1);
- close(pfd[1]);
+ close(d->pfd[0]);
+ dup(d->infd, 0);
+ close(d->infd);
+ dup(d->pfd[1], 1);
+ close(d->pfd[1]);
- execl("/bin/tga", "tga", "-9t", nil);
+ snprint(buf, sizeof buf, "/bin/%s", d->prog);
+
+ execl(buf, d->prog, "-9t", nil);
threadexitsall("execl: %r");
}
-Memimage *
-readtga(char *path)
+static Memimage *
+genreadimage(char *prog, char *path)
{
Memimage *i;
- int fd, pfd[3];
+ Deco d;
- if(pipe(pfd) < 0)
+ d.prog = prog;
+
+ if(pipe(d.pfd) < 0)
sysfatal("pipe: %r");
- fd = open(path, OREAD);
- if(fd < 0)
+ d.infd = open(path, OREAD);
+ if(d.infd < 0)
sysfatal("open: %r");
- pfd[2] = fd;
- procrfork(decproc, pfd, mainstacksize, RFFDG|RFNAMEG|RFNOTEG);
- close(pfd[1]);
- i = readmemimage(pfd[0]);
- close(pfd[0]);
- close(fd);
+ procrfork(decproc, &d, mainstacksize, RFFDG|RFNAMEG|RFNOTEG);
+ close(d.pfd[1]);
+ i = readmemimage(d.pfd[0]);
+ close(d.pfd[0]);
+ close(d.infd);
return i;
+}
+
+Memimage *
+readtga(char *path)
+{
+ return genreadimage("tga", path);
+}
+
+Memimage *
+readpng(char *path)
+{
+ return genreadimage("png", path);
}
Memimage *