aboutsummaryrefslogtreecommitdiff
path: root/libobj/obj.c
diff options
context:
space:
mode:
Diffstat (limited to 'libobj/obj.c')
-rw-r--r--libobj/obj.c584
1 files changed, 0 insertions, 584 deletions
diff --git a/libobj/obj.c b/libobj/obj.c
deleted file mode 100644
index 1575f70..0000000
--- a/libobj/obj.c
+++ /dev/null
@@ -1,584 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <ctype.h>
-#include <bio.h>
-#include "../obj.h"
-
-#undef isspace(c)
-#define isspace(c) ((c) == ' ' || (c) == '\t')
-
-typedef struct Line Line;
-struct Line
-{
- char *file;
- ulong lineno;
-};
-
-static Line curline;
-
-static void
-error(char *fmt, ...)
-{
- va_list va;
- char buf[ERRMAX], *bp;
-
- va_start(va, fmt);
- bp = seprint(buf, buf + sizeof buf, "%s:%lud ", curline.file, curline.lineno);
- vseprint(bp, buf + sizeof buf, fmt, va);
- va_end(va);
- werrstr("%s\n", buf);
-}
-
-static void *
-emalloc(ulong n)
-{
- void *p;
-
- p = malloc(n);
- if(p == nil)
- sysfatal("malloc: %r");
- memset(p, 0, n);
- setmalloctag(p, getcallerpc(&n));
- return p;
-}
-
-static void *
-erealloc(void *v, ulong n)
-{
- void *nv;
-
- nv = realloc(v, n);
- if(nv == nil)
- sysfatal("realloc: %r");
- setrealloctag(nv, getcallerpc(&v));
- return nv;
-}
-
-static uint
-hash(char *s)
-{
- uint h;
-
- h = 0x811c9dc5;
- while(*s != 0)
- h = (h^(uchar)*s++) * 0x1000193;
- return h % OBJHTSIZE;
-}
-
-static void
-addvertva(OBJVertexArray *va, OBJVertex v)
-{
- va->verts = erealloc(va->verts, ++va->nvert*sizeof(OBJVertex));
- va->verts[va->nvert-1] = v;
-}
-
-static void
-addvert(OBJ *obj, OBJVertex v, int vtype)
-{
- addvertva(&obj->vertdata[vtype], v);
-}
-
-static void
-addelem(OBJObject *o, OBJElem *e)
-{
- OBJElem *ep;
-
- if(o->child == nil){
- o->child = e;
- return;
- }
- for(ep = o->child; ep->next != nil; ep = ep->next)
- ;
- ep->next = e;
-}
-
-static OBJElem *
-allocelem(int t)
-{
- OBJElem *e;
-
- e = emalloc(sizeof(OBJElem));
- e->type = t;
- return e;
-}
-
-static void
-addelemidx(OBJElem *e, int idx)
-{
- e->indices = erealloc(e->indices, ++e->nindex*sizeof(int));
- e->indices[e->nindex-1] = idx;
-}
-
-static void
-freeelem(OBJElem *e)
-{
- free(e->indices);
- free(e);
-}
-
-static OBJObject *
-alloco(char *n)
-{
- OBJObject *o;
-
- o = emalloc(sizeof(OBJObject));
- o->name = strdup(n);
- return o;
-}
-
-static void
-freeo(OBJObject *o)
-{
- OBJElem *e, *ne;
-
- free(o->name);
- for(e = o->child; e != nil; e = ne){
- ne = e->next;
- freeelem(e);
- }
- free(o);
-}
-
-static void
-pusho(OBJ *obj, OBJObject *o)
-{
- OBJObject *op, *prev;
- uint h;
-
- prev = nil;
- h = hash(o->name);
- for(op = obj->objtab[h]; op != nil; prev = op, op = op->next)
- if(strcmp(op->name, o->name) == 0){
- o->next = op->next;
- freeo(op);
- break;
- }
- if(prev == nil){
- obj->objtab[h] = o;
- return;
- }
- prev->next = o;
-}
-
-static OBJObject *
-geto(OBJ *obj, char *n)
-{
- OBJObject *o;
- uint h;
-
- h = hash(n);
- for(o = obj->objtab[h]; o != nil; o = o->next)
- if(strcmp(o->name, n) == 0)
- break;
- return o;
-}
-
-OBJ *
-objparse(char *file)
-{
- Biobuf *bin;
- OBJ *obj;
- OBJObject *o;
- OBJElem *e;
- OBJVertex v;
- double *d;
- char c, buf[256], *p;
- int vtype, idx, sign;
-
- o = nil;
- bin = Bopen(file, OREAD);
- if(bin == nil)
- sysfatal("Bopen: %r");
- curline.file = file;
- curline.lineno = 1;
- obj = emalloc(sizeof(OBJ));
- while((c = Bgetc(bin)) != Beof){
- switch(c){
- case 'v':
- d = (double*)&v;
- c = Bgetc(bin);
- vtype = OBJVGeometric;
- switch(c){
- case 't': vtype = OBJVTexture; break;
- case 'p': vtype = OBJVParametric; break;
- case 'n': vtype = OBJVNormal; break;
- default:
- if(!isspace(c)){
- error("wrong vertex type");
- goto error;
- }
- }
- while(c = Bgetc(bin), c != Beof && c != '\n' && d-(double*)&v < 4){
- while(isspace(c))
- c = Bgetc(bin);
- if(c == '\\'){
- while(c != '\n')
- c = Bgetc(bin);
- continue;
- }
- if(c != '-' && !isdigit(c)){
- error("unexpected character '%c'", c);
- goto error;
- }
- Bungetc(bin);
- Bgetd(bin, d++);
- }
- switch(vtype){
- case OBJVGeometric:
- if(d-(double*)&v < 3){
- error("not enough coordinates");
- goto error;
- }
- if(d-(double*)&v < 4)
- *d = 1; /* default w value */
- break;
- case OBJVTexture:
- if(d-(double*)&v < 1){
- error("not enough coordinates");
- goto error;
- }
- while(d-(double*)&v < 3)
- *d++ = 0; /* default v and w values */
- break;
- case OBJVParametric:
- if(d-(double*)&v < 2){
- error("not enough coordinates");
- goto error;
- }
- if(d-(double*)&v < 3)
- *d = 1; /* default w value */
- break;
- case OBJVNormal:
- if(d-(double*)&v < 3){
- error("not enough coordinates");
- goto error;
- }
- }
- addvert(obj, v, vtype);
- break;
- case 'o':
- p = buf;
- c = Bgetc(bin);
- if(!isspace(c)){
- error("syntax error");
- goto error;
- }
- while(isspace(c))
- c = Bgetc(bin);
- if(!isalnum(c)){
- error("unexpected character '%c'", c);
- goto error;
- }
- do{
- *p++ = c;
- }while(c = Bgetc(bin), isalnum(c) && p-buf < sizeof(buf)-1);
- *p = 0;
- o = geto(obj, buf);
- if(o == nil){
- o = alloco(buf);
- pusho(obj, o);
- }
- break;
- case 'g':
- case 's':
- /* element and smoothing groups ignored for now */
- while(c != '\n')
- c = Bgetc(bin);
- break;
- case 'p':
- c = Bgetc(bin);
- if(!isspace(c)){
- error("syntax error");
- goto error;
- }
- while(c = Bgetc(bin), c != '\n'){
- idx = 0;
- sign = 0;
- while(isspace(c))
- c = Bgetc(bin);
- if(c == '\\'){
- while(c != '\n')
- c = Bgetc(bin);
- continue;
- }
- if(c != '-' && !isdigit(c)){
- error("unexpected character '%c'", c);
- goto error;
- }
- if(c == '-'){
- sign = 1;
- c = Bgetc(bin);
- if(!isdigit(c)){
- error("unexpected character '%c'", c);
- goto error;
- }
- }
- do{
- idx = idx*10 + c-'0';
- }while(c = Bgetc(bin), isdigit(c));
- Bungetc(bin);
- idx = sign ? obj->vertdata[OBJVGeometric].nvert-idx : idx-1;
- if(idx+1 > obj->vertdata[OBJVGeometric].nvert){
- error("not enough vertices");
- goto error;
- }
- e = allocelem(OBJEPoint);
- addelemidx(e, idx);
- if(o == nil){
- o = alloco("default");
- pusho(obj, o);
- }
- addelem(o, e);
- }
- break;
- case 'l':
- c = Bgetc(bin);
- if(!isspace(c)){
- error("syntax error");
- goto error;
- }
- while(c = Bgetc(bin), c != '\n'){
- idx = 0;
- sign = 0;
- while(isspace(c))
- c = Bgetc(bin);
- if(c == '\\'){
- while(c != '\n')
- c = Bgetc(bin);
- continue;
- }
- if(c != '-' && !isdigit(c)){
- error("unexpected character '%c'", c);
- goto error;
- }
- if(c == '-'){
- sign = 1;
- c = Bgetc(bin);
- if(!isdigit(c)){
- error("unexpected character '%c'", c);
- goto error;
- }
- }
- do{
- idx = idx*10 + c-'0';
- }while(c = Bgetc(bin), isdigit(c));
- idx = sign ? obj->vertdata[OBJVGeometric].nvert-idx : idx-1;
- if(idx+1 > obj->vertdata[OBJVGeometric].nvert){
- error("not enough vertices");
- goto error;
- }
- e = allocelem(OBJELine);
- addelemidx(e, idx);
-Line2:
- idx = 0;
- sign = 0;
- while(isspace(c))
- c = Bgetc(bin);
- if(c == '\\'){
- while(c != '\n')
- c = Bgetc(bin);
- c = Bgetc(bin);
- goto Line2;
- }
- if(c != '-' && !isdigit(c)){
- freeelem(e);
- error("unexpected character '%c'", c);
- goto error;
- }
- if(c == '-'){
- sign = 1;
- c = Bgetc(bin);
- if(!isdigit(c)){
- freeelem(e);
- error("unexpected character '%c'", c);
- goto error;
- }
- }
- do{
- idx = idx*10 + c-'0';
- }while(c = Bgetc(bin), isdigit(c));
- Bungetc(bin);
- idx = sign ? obj->vertdata[OBJVGeometric].nvert-idx : idx-1;
- if(idx+1 > obj->vertdata[OBJVGeometric].nvert){
- freeelem(e);
- error("not enough vertices");
- goto error;
- }
- addelemidx(e, idx);
- if(o == nil){
- o = alloco("default");
- pusho(obj, o);
- }
- addelem(o, e);
- }
- break;
- case 'f':
- e = allocelem(OBJEFace);
- c = Bgetc(bin);
- if(!isspace(c)){
- freeelem(e);
- error("syntax error");
- goto error;
- }
- while(c = Bgetc(bin), c != '\n'){
- idx = 0;
- sign = 0;
- while(isspace(c))
- c = Bgetc(bin);
- if(c == '\\'){
- while(c != '\n')
- c = Bgetc(bin);
- continue;
- }
- if(c != '-' && !isdigit(c)){
- freeelem(e);
- error("unexpected character '%c'", c);
- goto error;
- }
- if(c == '-'){
- sign = 1;
- c = Bgetc(bin);
- if(!isdigit(c)){
- freeelem(e);
- error("unexpected character '%c'", c);
- goto error;
- }
- }
- do{
- idx = idx*10 + c-'0';
- }while(c = Bgetc(bin), isdigit(c));
- Bungetc(bin);
- idx = sign ? obj->vertdata[OBJVGeometric].nvert-idx : idx-1;
- if(idx+1 > obj->vertdata[OBJVGeometric].nvert){
- freeelem(e);
- error("not enough vertices");
- goto error;
- }
- addelemidx(e, idx);
- }
- if(o == nil){
- o = alloco("default");
- pusho(obj, o);
- }
- addelem(o, e);
- break;
- case 'm':
- case 'u':
- p = buf;
- do{
- *p++ = c;
- }while(c = Bgetc(bin), isalpha(c) && p-buf < sizeof(buf)-1);
- *p = 0;
- if(strcmp(buf, "mtllib") != 0 && strcmp(buf, "usemtl") != 0){
- error("syntax error");
- goto error;
- }
- while(c != '\n')
- c = Bgetc(bin);
- break;
- case '#':
- while(c != '\n')
- c = Bgetc(bin);
- break;
- }
- do{
- if(c == '\n'){
- curline.lineno++;
- break;
- }
- if(!isspace(c)){
- error("syntax error");
- goto error;
- }
- }while((c = Bgetc(bin)) != Beof);
- }
- Bterm(bin);
- return obj;
-error:
- objfree(obj);
- Bterm(bin);
- return nil;
-}
-
-void
-objfree(OBJ *obj)
-{
- OBJObject *o, *no;
- int i;
-
- if(obj == nil)
- return;
- for(i = 0; i < nelem(obj->vertdata); i++)
- free(obj->vertdata[i].verts);
- for(i = 0; i < nelem(obj->objtab); i++)
- for(o = obj->objtab[i]; o != nil; o = no){
- no = o->next;
- freeo(o);
- }
- free(obj);
-}
-
-int
-OBJfmt(Fmt *f)
-{
- OBJ *obj;
- OBJObject *o;
- OBJElem *e;
- OBJVertex v;
- int i, j, r, pack;
-
- r = pack = 0;
- obj = va_arg(f->args, OBJ*);
- for(i = 0; i < nelem(obj->vertdata); i++)
- for(j = 0; j < obj->vertdata[i].nvert; j++){
- v = obj->vertdata[i].verts[j];
- switch(i){
- case OBJVGeometric:
- r += fmtprint(f, "v %g %g %g %g\n", v.x, v.y, v.z, v.w);
- break;
- case OBJVTexture:
- r += fmtprint(f, "vt %g %g %g\n", v.u, v.v, v.vv);
- break;
- case OBJVNormal:
- r += fmtprint(f, "vn %g %g %g\n", v.i, v.j, v.k);
- break;
- case OBJVParametric:
- r += fmtprint(f, "vp %g %g %g\n", v.u, v.v, v.vv);
- break;
- }
- }
- for(i = 0; i < nelem(obj->objtab); i++)
- for(o = obj->objtab[i]; o != nil; o = o->next){
- if(strcmp(o->name, "default") != 0)
- r += fmtprint(f, "o %s\n", o->name);
- for(e = o->child; e != nil; e = e->next){
- switch(e->type){
- case OBJEPoint:
- if(pack == 0)
- r += fmtprint(f, "p");
- pack = pack > 0 ? --pack : 8-1;
- break;
- case OBJELine:
- r += fmtprint(f, "l");
- break;
- case OBJEFace:
- r += fmtprint(f, "f");
- break;
- //case OBJECurve:
- //case OBJECurve2:
- //case OBJESurface:
- }
- for(j = 0; j < e->nindex; j++)
- r += fmtprint(f, " %d", e->indices[j]+1);
- if(e->type != OBJEPoint || pack == 0)
- r += fmtprint(f, "\n");
- }
- }
- return r;
-}
-
-void
-OBJfmtinstall(void)
-{
- fmtinstall('O', OBJfmt);
-}