From 5a6f5e0d2e19b72a4264eeb6300a9352901c8a42 Mon Sep 17 00:00:00 2001 From: rodri Date: Wed, 6 Mar 2024 22:04:06 +0000 Subject: add support to load diffuse color texture maps. --- obj.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- obj.h | 2 +- 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/obj.c b/obj.c index 37df37a..e1b1b4e 100644 --- a/obj.c +++ b/obj.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include #undef isspace(c) @@ -96,6 +98,80 @@ hash(char *s) return h % OBJHTSIZE; } +typedef struct Deco Deco; +struct Deco +{ + int pfd[2]; + int infd; + char *prog; +}; + +static void +decproc(void *arg) +{ + char buf[32]; + Deco *d; + + d = arg; + + close(d->pfd[0]); + dup(d->infd, 0); + close(d->infd); + dup(d->pfd[1], 1); + close(d->pfd[1]); + + snprint(buf, sizeof buf, "/bin/%s", d->prog); + + execl(buf, d->prog, "-9t", nil); + sysfatal("execl: %r"); +} + +static Memimage * +genreadimage(char *prog, char *path) +{ + Memimage *i; + Deco d; + + d.prog = prog; + + if(pipe(d.pfd) < 0) + sysfatal("pipe: %r"); + d.infd = open(path, OREAD); + if(d.infd < 0) + sysfatal("open: %r"); + switch(fork()){ + case -1: + sysfatal("fork: %r"); + case 0: + decproc(&d); + default: + close(d.pfd[1]); + i = readmemimage(d.pfd[0]); + close(d.pfd[0]); + close(d.infd); + } + + return i; +} + +static Memimage * +readtga(char *path) +{ + return genreadimage("tga", path); +} + +static Memimage * +readpng(char *path) +{ + return genreadimage("png", path); +} + +static Memimage * +readjpg(char *path) +{ + return genreadimage("jpg", path); +} + static void addvertva(OBJVertexArray *va, OBJVertex v) { @@ -277,7 +353,7 @@ objmtlparse(char *file) OBJMaterlist *ml; OBJMaterial *m; Biobuf *bin; - char *line, *f[10], *p, buf[128]; + char *line, *f[10], *p, *ext, buf[128]; int nf; if((p = strrchr(curline.file, '/')) != nil) @@ -374,6 +450,30 @@ objmtlparse(char *file) } m->d = strtod(f[1], nil); } + if(nf == 2 && strcmp(f[0], "map_Kd") == 0){ + if(m == nil){ + mterror("no material found"); + goto error; + } + ext = strrchr(f[1], '.'); + if(ext++ != nil){ + snprint(buf, sizeof buf, "%.*s/%s", (int)(p-curline.file), curline.file, f[1]); + if(strcmp(ext, "tga") == 0) + m->map_Kd = readtga(buf); + else if(strcmp(ext, "png") == 0) + m->map_Kd = readpng(buf); + else if(strcmp(ext, "jpg") == 0) + m->map_Kd = readjpg(buf); + else{ + mterror("file format not supported"); + goto error; + } + if(m->map_Kd == nil){ + mterror("read%s: %r", ext); + goto error; + } + } + } if(nf == 2 && strcmp(f[0], "illum") == 0){ if(m == nil){ mterror("no material found"); @@ -401,6 +501,7 @@ objmtlfree(OBJMaterlist *ml) for(i = 0; i < nelem(ml->mattab); i++) for(m = ml->mattab[i]; m != nil; m = nm){ nm = m->next; + freememimage(m->map_Kd); freemt(m); } free(ml->filename); diff --git a/obj.h b/obj.h index f1edfb1..5ca2676 100644 --- a/obj.h +++ b/obj.h @@ -74,7 +74,7 @@ struct OBJMaterial double Ni; /* index of refraction */ double d; /* dissolution factor */ int illum; /* illumination model */ - double map_Kd; /* color texture file */ + Memimage *map_Kd; /* color texture file */ OBJMaterial *next; }; -- cgit v1.2.3