summaryrefslogtreecommitdiff
path: root/vertex.c
diff options
context:
space:
mode:
Diffstat (limited to 'vertex.c')
-rw-r--r--vertex.c148
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);
+}