ref: 0f0a9514ccabd558e9b6610e7c6150a69e6f9bcd
parent: b4f6e218fccb523c9449a94b30cd6b2fa876a361
author: rodri <rgl@antares-labs.eu>
date: Mon Oct 7 14:32:50 EDT 2024
leave a single, general error reporting fn. add specular map support. improvements to path handling.
--- a/obj.c
+++ b/obj.c
@@ -13,38 +13,22 @@
struct Line
{
char *file;
- ulong lineno;
+ ulong line;
};
-static Line curline;
-static Line curmtline;
-
static void
-error(char *fmt, ...)
+error(Line *l, 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);
+ bp = seprint(buf, buf + sizeof buf, "%s:%lud ", l->file, l->line);
vseprint(bp, buf + sizeof buf, fmt, va);
va_end(va);
werrstr("%s", buf);
}
-static void
-mterror(char *fmt, ...)
-{
- va_list va;
- char buf[ERRMAX], *bp;
-
- va_start(va, fmt);
- bp = seprint(buf, buf + sizeof buf, "%s:%lud ", curmtline.file, curmtline.lineno);
- vseprint(bp, buf + sizeof buf, fmt, va);
- va_end(va);
- werrstr("%s", buf);
-}
-
static void *
emalloc(ulong n)
{
@@ -321,6 +305,7 @@
freemt(OBJMaterial *m)
{
freememimage(m->norm);
+ freememimage(m->map_Ks);
freememimage(m->map_Kd);
free(m->name);
free(m);
@@ -374,28 +359,35 @@
OBJMaterlist *
objmtlparse(char *file)
{
+ Line curline;
OBJMaterlist *ml;
OBJMaterial *m;
Biobuf *bin;
- char *line, *f[10], *p, buf[128];
+ char *line, *f[10], *p, wdir[128], buf[128];
int nf;
- if((p = strrchr(curline.file, '/')) != nil)
- snprint(buf, sizeof buf, "%.*s/%s", (int)(p-curline.file), curline.file, file);
- else
- snprint(buf, sizeof buf, "%s", file);
-
- bin = Bopen(buf, OREAD);
- if(bin == nil)
+ bin = Bopen(file, OREAD);
+ if(bin == nil){
+ werrstr("Bopen: %r");
return nil;
+ }
+ if((p = strrchr(file, '/')) != nil){
+ *p++ = 0;
+ snprint(wdir, sizeof wdir, "%s", file);
+ file = p;
+ }else{
+ wdir[0] = '.';
+ wdir[1] = 0;
+ }
+
ml = allocmtl(file);
m = nil;
- curmtline.file = file;
- curmtline.lineno = 0;
+ curline.file = file;
+ curline.line = 0;
while((line = Brdline(bin, '\n')) != nil){
- curmtline.lineno++;
+ curline.line++;
line[Blinelen(bin)-1] = 0;
nf = tokenize(line, f, nelem(f));
@@ -404,7 +396,7 @@
if(strcmp(f[0], "newmtl") == 0){
if(nf != 2){
- mterror("syntax error");
+ error(&curline, "syntax error");
goto error;
}
m = allocmt(f[1]);
@@ -411,11 +403,11 @@
addmtl(ml, m);
}else if(strcmp(f[0], "Ka") == 0){
if(nf != 2 && nf != 4){
- mterror("syntax error");
+ error(&curline, "syntax error");
goto error;
}
if(m == nil){
- mterror("no material found");
+ error(&curline, "no material found");
goto error;
}
if(nf == 2)
@@ -428,11 +420,11 @@
m->Ka.a = 1;
}else if(strcmp(f[0], "Kd") == 0){
if(nf != 2 && nf != 4){
- mterror("syntax error");
+ error(&curline, "syntax error");
goto error;
}
if(m == nil){
- mterror("no material found");
+ error(&curline, "no material found");
goto error;
}
if(nf == 2)
@@ -445,11 +437,11 @@
m->Kd.a = 1;
}else if(strcmp(f[0], "Ks") == 0){
if(nf != 2 && nf != 4){
- mterror("syntax error");
+ error(&curline, "syntax error");
goto error;
}
if(m == nil){
- mterror("no material found");
+ error(&curline, "no material found");
goto error;
}
if(nf == 2)
@@ -462,11 +454,11 @@
m->Ks.a = 1;
}else if(strcmp(f[0], "Ke") == 0){
if(nf != 2 && nf != 4){
- mterror("syntax error");
+ error(&curline, "syntax error");
goto error;
}
if(m == nil){
- mterror("no material found");
+ error(&curline, "no material found");
goto error;
}
if(nf == 2)
@@ -479,75 +471,83 @@
m->Ke.a = 1;
}else if(strcmp(f[0], "Ns") == 0){
if(nf != 2){
- mterror("syntax error");
+ error(&curline, "syntax error");
goto error;
}
if(m == nil){
- mterror("no material found");
+ error(&curline, "no material found");
goto error;
}
m->Ns = strtod(f[1], nil);
}else if(strcmp(f[0], "Ni") == 0){
if(nf != 2){
- mterror("syntax error");
+ error(&curline, "syntax error");
goto error;
}
if(m == nil){
- mterror("no material found");
+ error(&curline, "no material found");
goto error;
}
m->Ni = strtod(f[1], nil);
}else if(strcmp(f[0], "d") == 0){
if(nf != 2){
- mterror("syntax error");
+ error(&curline, "syntax error");
goto error;
}
if(m == nil){
- mterror("no material found");
+ error(&curline, "no material found");
goto error;
}
m->d = strtod(f[1], nil);
}else if(strcmp(f[0], "map_Kd") == 0){
if(nf != 2){
- mterror("syntax error");
+ error(&curline, "syntax error");
goto error;
}
if(m == nil){
- mterror("no material found");
+ error(&curline, "no material found");
goto error;
}
- if(p != nil)
- snprint(buf, sizeof buf, "%.*s/%s", (int)(p-curline.file), curline.file, f[1]);
- else
- snprint(buf, sizeof buf, "%s", f[1]);
+ snprint(buf, sizeof buf, "%s/%s", wdir, f[1]);
if((m->map_Kd = readimagefile(buf)) == nil){
- mterror("readimagefile: %r");
+ error(&curline, "readimagefile: %r");
goto error;
}
+ }else if(strcmp(f[0], "map_Ks") == 0){
+ if(nf != 2){
+ error(&curline, "syntax error");
+ goto error;
+ }
+ if(m == nil){
+ error(&curline, "no material found");
+ goto error;
+ }
+ snprint(buf, sizeof buf, "%s/%s", wdir, f[1]);
+ if((m->map_Ks = readimagefile(buf)) == nil){
+ error(&curline, "readimagefile: %r");
+ goto error;
+ }
}else if(strcmp(f[0], "norm") == 0){
if(nf != 2){
- mterror("syntax error");
+ error(&curline, "syntax error");
goto error;
}
if(m == nil){
- mterror("no material found");
+ error(&curline, "no material found");
goto error;
}
- if(p != nil)
- snprint(buf, sizeof buf, "%.*s/%s", (int)(p-curline.file), curline.file, f[1]);
- else
- snprint(buf, sizeof buf, "%s", f[1]);
+ snprint(buf, sizeof buf, "%s/%s", wdir, f[1]);
if((m->norm = readimagefile(buf)) == nil){
- mterror("readimagefile: %r");
+ error(&curline, "readimagefile: %r");
goto error;
}
}else if(strcmp(f[0], "illum") == 0){
if(nf != 2){
- mterror("syntax error");
+ error(&curline, "syntax error");
goto error;
}
if(m == nil){
- mterror("no material found");
+ error(&curline, "no material found");
goto error;
}
m->illum = strtol(f[1], nil, 10);
@@ -582,6 +582,7 @@
objparse(char *file)
{
Biobuf *bin;
+ Line curline;
OBJ *obj;
OBJObject *o;
OBJMaterial *m;
@@ -588,7 +589,7 @@
OBJElem *e;
OBJVertex v;
double *d;
- char c, buf[256], *p;
+ char c, wdir[128], buf[256], *p;
int vtype, idxtab, idx, sign;
m = nil;
@@ -596,8 +597,16 @@
bin = Bopen(file, OREAD);
if(bin == nil)
sysfatal("Bopen: %r");
+ if((p = strrchr(file, '/')) != nil){
+ *p++ = 0;
+ snprint(wdir, sizeof wdir, "%s", file);
+ file = p;
+ }else{
+ wdir[0] = '.';
+ wdir[1] = 0;
+ }
curline.file = file;
- curline.lineno = 1;
+ curline.line = 1;
obj = emalloc(sizeof(OBJ));
while((c = Bgetc(bin)) != Beof){
switch(c){
@@ -611,7 +620,7 @@
case 'n': vtype = OBJVNormal; break;
default:
if(!isspace(c)){
- error("wrong vertex type");
+ error(&curline, "wrong vertex type");
goto error;
}
}
@@ -624,7 +633,7 @@
continue;
}
if(c != '-' && !isdigit(c)){
- error("unexpected character '%c'", c);
+ error(&curline, "unexpected character '%c'", c);
goto error;
}
Bungetc(bin);
@@ -633,7 +642,7 @@
switch(vtype){
case OBJVGeometric:
if(d-(double*)&v < 3){
- error("not enough coordinates");
+ error(&curline, "not enough coordinates");
goto error;
}
if(d-(double*)&v < 4)
@@ -641,7 +650,7 @@
break;
case OBJVTexture:
if(d-(double*)&v < 1){
- error("not enough coordinates");
+ error(&curline, "not enough coordinates");
goto error;
}
while(d-(double*)&v < 3)
@@ -649,7 +658,7 @@
break;
case OBJVParametric:
if(d-(double*)&v < 2){
- error("not enough coordinates");
+ error(&curline, "not enough coordinates");
goto error;
}
if(d-(double*)&v < 3)
@@ -657,7 +666,7 @@
break;
case OBJVNormal:
if(d-(double*)&v < 3){
- error("not enough coordinates");
+ error(&curline, "not enough coordinates");
goto error;
}
}
@@ -667,13 +676,13 @@
p = buf;
c = Bgetc(bin);
if(!isspace(c)){
- error("syntax error");
+ error(&curline, "syntax error");
goto error;
}
while(isspace(c))
c = Bgetc(bin);
if(!isalnum(c)){
- error("unexpected character '%c'", c);
+ error(&curline, "unexpected character '%c'", c);
goto error;
}
do{
@@ -695,7 +704,7 @@
case 'p':
c = Bgetc(bin);
if(!isspace(c)){
- error("syntax error");
+ error(&curline, "syntax error");
goto error;
}
while(c = Bgetc(bin), c != '\n'){
@@ -709,7 +718,7 @@
continue;
}
if(c != '-' && !isdigit(c)){
- error("unexpected character '%c'", c);
+ error(&curline, "unexpected character '%c'", c);
goto error;
}
if(c == '-'){
@@ -716,7 +725,7 @@
sign = 1;
c = Bgetc(bin);
if(!isdigit(c)){
- error("unexpected character '%c'", c);
+ error(&curline, "unexpected character '%c'", c);
goto error;
}
}
@@ -726,7 +735,7 @@
Bungetc(bin);
idx = sign ? obj->vertdata[OBJVGeometric].nvert-idx : idx-1;
if(idx+1 > obj->vertdata[OBJVGeometric].nvert){
- error("not enough vertices");
+ error(&curline, "not enough vertices");
goto error;
}
e = allocelem(OBJEPoint);
@@ -743,7 +752,7 @@
case 'l':
c = Bgetc(bin);
if(!isspace(c)){
- error("syntax error");
+ error(&curline, "syntax error");
goto error;
}
while(c = Bgetc(bin), c != '\n'){
@@ -757,7 +766,7 @@
continue;
}
if(c != '-' && !isdigit(c)){
- error("unexpected character '%c'", c);
+ error(&curline, "unexpected character '%c'", c);
goto error;
}
if(c == '-'){
@@ -764,7 +773,7 @@
sign = 1;
c = Bgetc(bin);
if(!isdigit(c)){
- error("unexpected character '%c'", c);
+ error(&curline, "unexpected character '%c'", c);
goto error;
}
}
@@ -773,7 +782,7 @@
}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");
+ error(&curline, "not enough vertices");
goto error;
}
e = allocelem(OBJELine);
@@ -791,7 +800,7 @@
}
if(c != '-' && !isdigit(c)){
freeelem(e);
- error("unexpected character '%c'", c);
+ error(&curline, "unexpected character '%c'", c);
goto error;
}
if(c == '-'){
@@ -799,7 +808,7 @@
c = Bgetc(bin);
if(!isdigit(c)){
freeelem(e);
- error("unexpected character '%c'", c);
+ error(&curline, "unexpected character '%c'", c);
goto error;
}
}
@@ -810,7 +819,7 @@
idx = sign ? obj->vertdata[OBJVGeometric].nvert-idx : idx-1;
if(idx+1 > obj->vertdata[OBJVGeometric].nvert){
freeelem(e);
- error("not enough vertices");
+ error(&curline, "not enough vertices");
goto error;
}
addelemidx(e, OBJVGeometric, idx);
@@ -829,7 +838,7 @@
c = Bgetc(bin);
if(!isspace(c)){
freeelem(e);
- error("syntax error");
+ error(&curline, "syntax error");
goto error;
}
while(c = Bgetc(bin), c != '\n'){
@@ -847,7 +856,7 @@
if(c == '/'){
if(++idxtab >= OBJNVERT){
freeelem(e);
- error("unknown vertex type '%d'", idxtab);
+ error(&curline, "unknown vertex type '%d'", idxtab);
goto error;
}
continue;
@@ -854,7 +863,7 @@
}
if(c != '-' && !isdigit(c)){
freeelem(e);
- error("unexpected character '%c'", c);
+ error(&curline, "unexpected character '%c'", c);
goto error;
}
if(c == '-'){
@@ -862,7 +871,7 @@
c = Bgetc(bin);
if(!isdigit(c)){
freeelem(e);
- error("unexpected character '%c'", c);
+ error(&curline, "unexpected character '%c'", c);
goto error;
}
}
@@ -873,7 +882,7 @@
idx = sign ? obj->vertdata[idxtab].nvert-idx : idx-1;
if(idx+1 > obj->vertdata[idxtab].nvert){
freeelem(e);
- error("not enough vertices");
+ error(&curline, "not enough vertices");
goto error;
}
addelemidx(e, idxtab, idx);
@@ -896,14 +905,14 @@
if(strcmp(buf, "mtllib") == 0){
while(isspace(c))
c = Bgetc(bin);
- p = buf;
+ p = seprint(buf, buf + sizeof buf, "%s/", wdir);
do{
*p++ = c;
}while(c = Bgetc(bin), (isalnum(c) || c == '.' || c == '_' || c == '-') && p-buf < sizeof(buf)-1);
*p = 0;
if((obj->materials = objmtlparse(buf)) == nil){
- error("objmtlparse: %r");
- fprint(2, "%r");
+ error(&curline, "warning: objmtlparse: %r");
+ fprint(2, "%r\n");
}
}else if(strcmp(buf, "usemtl") == 0){
while(isspace(c))
@@ -914,11 +923,11 @@
}while(c = Bgetc(bin), (isalnum(c) || c == '.' || c == '_' || c == '-' || c == '(' || c == ')') && p-buf < sizeof(buf)-1);
*p = 0;
if(obj->materials != nil && (m = getmtl(obj->materials, buf)) == nil){
- error("no material '%s' found", buf);
+ error(&curline, "no material '%s' found", buf);
goto error;
}
}else{
- error("syntax error");
+ error(&curline, "syntax error");
goto error;
}
while(c != '\n')
@@ -931,11 +940,11 @@
}
do{
if(c == '\n'){
- curline.lineno++;
+ curline.line++;
break;
}
if(!isspace(c)){
- error("syntax error");
+ error(&curline, "syntax error");
goto error;
}
}while((c = Bgetc(bin)) != Beof);
--- a/obj.h
+++ b/obj.h
@@ -72,9 +72,10 @@
OBJColor Ke; /* emissive color */
double Ns; /* specular highlight */
double Ni; /* index of refraction */
- double d; /* dissolution factor */
+ double d; /* dissolution factor (opacity) */
int illum; /* illumination model */
Memimage *map_Kd; /* color texture file */
+ Memimage *map_Ks; /* specular texture file */
Memimage *norm; /* normal texture file */
OBJMaterial *next;
};