From fdae64883b3e079cbb624bb7a10d09952e191382 Mon Sep 17 00:00:00 2001 From: rodri Date: Sun, 12 Nov 2023 17:25:50 +0000 Subject: added texture mapping. --- main.c | 126 +++++++++++++++++++++++++++++++++---------- tex/african_head_diffuse.tga | Bin 0 -> 2801531 bytes 2 files changed, 98 insertions(+), 28 deletions(-) create mode 100644 tex/african_head_diffuse.tga diff --git a/main.c b/main.c index 4673e9e..1c735f9 100644 --- a/main.c +++ b/main.c @@ -35,6 +35,7 @@ Memimage *fb; double *zbuf; Memimage *red, *green, *blue; OBJ *model; +Memimage *modeltex; Channel *drawc; int nprocs; @@ -43,6 +44,28 @@ char winspec[32]; void resized(void); uvlong nanosec(void); +int +min(int a, int b) +{ + return a < b? a: b; +} + +int +max(int a, int b) +{ + return a > b? a: b; +} + +void +swap(int *a, int *b) +{ + int t; + + t = *a; + *a = *b; + *b = t; +} + void * emalloc(ulong n) { @@ -96,16 +119,43 @@ eallocmemimage(Rectangle r, ulong chan) return i; } -int -min(int a, int b) +static void +decproc(void *arg) { - return a < b? a: b; + int fd, *pfd; + + pfd = arg; + fd = pfd[2]; + + close(pfd[0]); + dup(fd, 0); + close(fd); + dup(pfd[1], 1); + close(pfd[1]); + + execl("/bin/tga", "tga", "-9t", nil); + threadexitsall("execl: %r"); } -int -max(int a, int b) +Memimage * +readtga(char *path) { - return a > b? a: b; + Memimage *i; + int fd, pfd[3]; + + if(pipe(pfd) < 0) + sysfatal("pipe: %r"); + fd = open(path, OREAD); + if(fd < 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); + + return i; } Memimage * @@ -129,16 +179,6 @@ pixel(Memimage *dst, Point p, Memimage *src) memimagedraw(dst, rectaddpt(Rect(0,0,1,1), p), src, ZP, nil, ZP, SoverD); } -void -swap(int *a, int *b) -{ - int t; - - t = *a; - *a = *b; - *b = t; -} - void bresenham(Memimage *dst, Point p0, Point p1, Memimage *src) { @@ -342,19 +382,20 @@ modelshader(Sparams *sp) { OBJObject *o; OBJElem *e; - OBJVertex *verts; + OBJVertex *verts, *tverts; /* geometric and texture vertices */ OBJIndexArray *idxtab; Triangle3 t; - Triangle2 st; + Triangle2 st, tt; /* screen and texture triangles */ Rectangle bbox; - Point3 bc; - static Point3 light = {0,0,-1,0}; /* global light field */ - Point3 n; + Point3 bc, n; /* barycentric coords and surface normal */ + static Point3 light = {0,0,-1,0}; /* global light field */ + Point tp; /* texture point */ int i; - uchar cbuf[4]; + uchar cbuf[4], cbuf2[4]; double z, intensity; verts = model->vertdata[OBJVGeometric].verts; + tverts = model->vertdata[OBJVTexture].verts; for(i = 0; i < nelem(model->objtab); i++) for(o = model->objtab[i]; o != nil; o = o->next) @@ -398,10 +439,33 @@ modelshader(Sparams *sp) if(intensity < 0) continue; - cbuf[0] = 0xFF; - cbuf[1] = 0xFF*intensity; - cbuf[2] = 0xFF*intensity; - cbuf[3] = 0xFF*intensity; + idxtab = &e->indextab[OBJVTexture]; + if(modeltex != nil && idxtab->nindex == 3){ + tt.p0 = Pt2(tverts[idxtab->indices[0]].u, tverts[idxtab->indices[0]].v, 1); + tt.p1 = Pt2(tverts[idxtab->indices[1]].u, tverts[idxtab->indices[1]].v, 1); + tt.p2 = Pt2(tverts[idxtab->indices[2]].u, tverts[idxtab->indices[2]].v, 1); + + tt.p0 = mulpt2(tt.p0, bc.x); + tt.p1 = mulpt2(tt.p1, bc.y); + tt.p2 = mulpt2(tt.p2, bc.z); + + tp.x = (tt.p0.x + tt.p1.x + tt.p2.x)*Dx(modeltex->r); + tp.y = Dy(modeltex->r)-(tt.p0.y + tt.p1.y + tt.p2.y)*Dy(modeltex->r); + + unloadmemimage(modeltex, rectaddpt(Rect(0,0,1,1), tp), cbuf2, sizeof cbuf2); + cbuf[0] = cbuf2[3]; + cbuf[1] = cbuf2[0]; + cbuf[2] = cbuf2[1]; + cbuf[3] = cbuf2[2]; + }else{ + cbuf[0] = 0xFF; + cbuf[1] = 0xFF; + cbuf[2] = 0xFF; + cbuf[3] = 0xFF; + } + cbuf[1] *= intensity; + cbuf[2] *= intensity; + cbuf[3] *= intensity; memfillcolor(sp->frag, *(ulong*)cbuf); return sp->frag; @@ -485,7 +549,7 @@ key(Rune r) void usage(void) { - fprint(2, "usage: %s [-n nprocs] [-m objfile]\n", argv0); + fprint(2, "usage: %s [-n nprocs] [-m objfile] [-t texfile]\n", argv0); exits("usage"); } @@ -495,10 +559,11 @@ threadmain(int argc, char *argv[]) Mousectl *mc; Keyboardctl *kc; Rune r; - char *mdlpath; + char *mdlpath, *texpath; GEOMfmtinstall(); mdlpath = nil; + texpath = nil; ARGBEGIN{ case 'n': nprocs = strtoul(EARGF(usage()), nil, 10); @@ -506,6 +571,9 @@ threadmain(int argc, char *argv[]) case 'm': mdlpath = EARGF(usage()); break; + case 't': + texpath = EARGF(usage()); + break; default: usage(); }ARGEND; if(argc != 0) @@ -535,6 +603,8 @@ threadmain(int argc, char *argv[]) if(mdlpath != nil && (model = objparse(mdlpath)) == nil) sysfatal("objparse: %r"); + if(texpath != nil && (modeltex = readtga(texpath)) == nil) + sysfatal("readtga: %r"); render(); diff --git a/tex/african_head_diffuse.tga b/tex/african_head_diffuse.tga new file mode 100644 index 0000000..bdd085f Binary files /dev/null and b/tex/african_head_diffuse.tga differ -- cgit v1.2.3