diff options
Diffstat (limited to 'vertex.c')
-rw-r--r-- | vertex.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/vertex.c b/vertex.c new file mode 100644 index 0000000..0cd6ce7 --- /dev/null +++ b/vertex.c @@ -0,0 +1,148 @@ +#include <u.h> +#include <libc.h> +#include <thread.h> +#include <draw.h> +#include <memdraw.h> +#include <geometry.h> +#include "libobj/obj.h" +#include "graphics.h" +#include "internal.h" + +static void +_addvattr(Vertex *v, Vertexattr *va) +{ + int i; + + for(i = 0; i < v->nattrs; i++) + if(strcmp(v->attrs[i].id, va->id) == 0){ + v->attrs[i] = *va; + return; + } + v->attrs = erealloc(v->attrs, ++v->nattrs*sizeof(*va)); + v->attrs[v->nattrs-1] = *va; +} + +static void +copyvattrs(Vertex *d, Vertex *s) +{ + int i; + + for(i = 0; i < s->nattrs; i++) + _addvattr(d, &s->attrs[i]); +} + +Vertex +dupvertex(Vertex *v) +{ + Vertex nv; + + nv = *v; + nv.attrs = nil; + nv.nattrs = 0; + copyvattrs(&nv, v); + return nv; +} + +void +lerpvertex(Vertex *v, Vertex *v0, Vertex *v1, double t) +{ + Vertexattr va; + int i; + + v->p = lerp3(v0->p, v1->p, t); + v->n = lerp3(v0->n, v1->n, t); + v->c = lerp3(v0->c, v1->c, t); + v->uv = lerp2(v0->uv, v1->uv, t); + v->attrs = nil; + v->nattrs = 0; + for(i = 0; i < v0->nattrs; i++){ + va.id = v0->attrs[i].id; + va.type = v0->attrs[i].type; + if(va.type == VAPoint) + va.p = lerp3(v0->attrs[i].p, v1->attrs[i].p, t); + else + va.n = flerp(v0->attrs[i].n, v1->attrs[i].n, t); + _addvattr(v, &va); + } +} + +/* + * perspective-correct barycentric attribute interpolation + */ +void +berpvertex(Vertex *v, Vertex *v0, Vertex *v1, Vertex *v2, Point3 bc) +{ + Vertexattr va; + int i; + + v->n = addpt3(addpt3( + mulpt3(v0->n, bc.x), + mulpt3(v1->n, bc.y)), + mulpt3(v2->n, bc.z)); + v->c = addpt3(addpt3( + mulpt3(v0->c, bc.x), + mulpt3(v1->c, bc.y)), + mulpt3(v2->c, bc.z)); + v->uv = addpt2(addpt2( + mulpt2(v0->uv, bc.x), + mulpt2(v1->uv, bc.y)), + mulpt2(v2->uv, bc.z)); + v->attrs = nil; + v->nattrs = 0; + for(i = 0; i < v0->nattrs; i++){ + va.id = v0->attrs[i].id; + va.type = v0->attrs[i].type; + if(va.type == VAPoint) + va.p = addpt3(addpt3( + mulpt3(v0->attrs[i].p, bc.x), + mulpt3(v1->attrs[i].p, bc.y)), + mulpt3(v2->attrs[i].p, bc.z)); + else + va.n = dotvec3(Vec3(v0->attrs[i].n, v1->attrs[i].n, v2->attrs[i].n), bc); + _addvattr(v, &va); + } +} + +void +addvattr(Vertex *v, char *id, int type, void *val) +{ + Vertexattr va; + + va.id = id; + va.type = type; + switch(type){ + case VAPoint: va.p = *(Point3*)val; break; + case VANumber: va.n = *(double*)val; break; + default: sysfatal("unknown vertex attribute type '%d'", type); + } + _addvattr(v, &va); +} + +Vertexattr * +getvattr(Vertex *v, char *id) +{ + int i; + + for(i = 0; i < v->nattrs; i++) + if(strcmp(v->attrs[i].id, id) == 0) + return &v->attrs[i]; + return nil; +} + +void +delvattrs(Vertex *v) +{ + free(v->attrs); + v->attrs= nil; + v->nattrs = 0; +} + +void +fprintvattrs(int fd, Vertex *v) +{ + int i; + + for(i = 0; i < v->nattrs; i++) + fprint(fd, "id %s type %d v %g\n", + v->attrs[i].id, v->attrs[i].type, v->attrs[i].n); +} |