# HG changeset patch # User John Tsiombikas # Date 1281720045 -3600 # Node ID 51f115e337c2b1436a5a6023d5ac6a8a58dbe97c # Parent 6c44e4b1726da7b13bc24286a33c4c74abb13f1e separated obj loading and vector class diff -r 6c44e4b1726d -r 51f115e337c2 rt.cl --- a/rt.cl Wed Aug 11 04:30:35 2010 +0100 +++ b/rt.cl Fri Aug 13 18:20:45 2010 +0100 @@ -212,8 +212,7 @@ float4 reflect(float4 v, float4 n) { - float4 res = 2.0f * dot(v, n) * n - v; - return res; + return 2.0f * dot(v, n) * n - v; } float4 transform(float4 v, global const float *xform) diff -r 6c44e4b1726d -r 51f115e337c2 src/scene.cc --- a/src/scene.cc Wed Aug 11 04:30:35 2010 +0100 +++ b/src/scene.cc Fri Aug 13 18:20:45 2010 +0100 @@ -1,130 +1,6 @@ -#include -#include -#include #include -#include -#include -#include -#include -#include #include "scene.h" -#ifndef PATH_MAX -#define PATH_MAX 512 -#endif - -using namespace std; - -#define COMMANDS \ - CMD(V), \ - CMD(VN), \ - CMD(VT), \ - CMD(F), \ - CMD(O), \ - CMD(G), \ - CMD(MTLLIB), \ - CMD(USEMTL), \ - CMD(NEWMTL), \ - CMD(KA), \ - CMD(KD), \ - CMD(KS), \ - CMD(KR), \ - CMD(NS), \ - CMD(NI), \ - CMD(D), \ - CMD(TR), \ - CMD(MAP_KD), \ - CMD(MAP_KS), \ - CMD(MAP_NS), \ - CMD(MAP_D), \ - CMD(REFL), \ - CMD(BUMP) - -#define CMD(x) CMD_##x -enum { - COMMANDS, - CMD_UNK -}; -#undef CMD - -#define CMD(x) #x -static const char *cmd_names[] = { - COMMANDS, - 0 -}; -#undef CMD - -struct Vector3 { - float x, y, z; - - Vector3() { x = y = z = 0.0; } - Vector3(float a, float b, float c) { x = a; y = b; z = c; } - - void normalize() { float len = sqrt(x * x + y * y + z * z); x /= len; y /= len; z /= len; } -}; - -struct Vector2 { - float x, y; - - Vector2() { x = y = 0.0; } - Vector2(float a, float b) { x = a; y = b; } -}; - -struct obj_face { - int elem; - int v[4], n[4], t[4]; -}; - -struct obj_file { - string cur_obj, cur_mat; - vector v, vn, vt; - vector f; -}; - -struct obj_mat { - string name; // newmtl - Vector3 ambient, diffuse, specular; // Ka, Kd, Ks - float shininess; // Ns - float ior; // Ni - float alpha; // d, Tr - float refl; // Kr (my extesnsion) - - string tex_dif, tex_spec, tex_shin, tex_alpha; // map_Kd, map_Ks, map_Ns, map_d - string tex_refl; // refl -type sphere|cube file - string tex_bump; // bump - - obj_mat() { reset(); } - - void reset() { - ambient = diffuse = Vector3(0.5, 0.5, 0.5); - specular = Vector3(0.0, 0.0, 0.0); - name = tex_dif = tex_spec = tex_shin = tex_alpha = tex_refl = tex_bump = ""; - shininess = 0; - ior = alpha = 1; - refl = 0.0; - } -}; - -static bool read_materials(FILE *fp, vector *vmtl); -static Mesh *cons_mesh(obj_file *obj); - -static int get_cmd(char *str); -static bool is_int(const char *str); -static bool is_float(const char *str); -static bool parse_vec(Vector3 *vec); -static bool parse_color(Vector3 *col); -static bool parse_face(obj_face *face); -static const char *parse_map(); - -static bool find_file(char *res, int sz, const char *fname, const char *path = ".", const char *mode = "rb"); -static const char *dirname(const char *str); - -static Vector3 operator -(const Vector3 &a, const Vector3 &b); -static Vector3 cross(const Vector3 &a, const Vector3 &b); - -static map matnames; - - #define FEQ(a, b) (fabs((a) - (b)) < 1e-8) bool Face::operator ==(const Face &f) const { @@ -188,568 +64,3 @@ } return &matlib[0]; } - - -#define INVALID_IDX INT_MIN - -#define SEP " \t\n\r\v" -#define BUF_SZ 512 - -bool Scene::load(const char *fname) -{ - FILE *fp; - - if(!(fp = fopen(fname, "rb"))) { - fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno)); - return false; - } - - bool res = load(fp); - fclose(fp); - return res; -} - -bool Scene::load(FILE *fp) -{ - static int seq; - char cur_name[16]; - - obj_file obj; - - sprintf(cur_name, "default%02d.obj", seq++); - obj.cur_obj = cur_name; - - int prev_cmd = 0, obj_added = 0; - for(;;) { - Vector3 vec; - obj_face face; - - char line[BUF_SZ]; - fgets(line, sizeof line, fp); - if(feof(fp)) { - break; - } - - char *tok; - if(!(tok = strtok(line, SEP))) { - continue; // ignore empty lines - } - - int cmd; - if((cmd = get_cmd(tok)) == -1) { - continue; // ignore unknown commands ... - } - - switch(cmd) { - case CMD_V: - if(!parse_vec(&vec)) { - continue; - } - obj.v.push_back(vec); - break; - - case CMD_VN: - if(!parse_vec(&vec)) { - continue; - } - obj.vn.push_back(vec); - break; - - case CMD_VT: - if(!parse_vec(&vec)) { - continue; - } - vec.y = 1.0 - vec.y; - obj.vt.push_back(vec); - break; - - case CMD_O: - case CMD_G: - if(prev_cmd == CMD_O || prev_cmd == CMD_G) { - break; // just in case we've got both of them in a row - } - /* if we have any previous data, group them up, add the object - * and continue with the new one... - */ - if(!obj.f.empty()) { - Mesh *mesh = cons_mesh(&obj); - mesh->matid = matnames[obj.cur_mat]; - add_mesh(mesh); - obj_added++; - - obj.f.clear(); // clean the face list - } - if((tok = strtok(0, SEP))) { - obj.cur_obj = tok; - } else { - sprintf(cur_name, "default%02d.obj", seq++); - obj.cur_obj = cur_name; - } - break; - - case CMD_MTLLIB: - if((tok = strtok(0, SEP))) { - char path[PATH_MAX]; - - sprintf(path, ".:%s", dirname(tok)); - if(!find_file(path, PATH_MAX, tok, path)) { - fprintf(stderr, "material library not found: %s\n", tok); - continue; - } - - FILE *mfile; - if(!(mfile = fopen(path, "rb"))) { - fprintf(stderr, "failed to open material library: %s\n", path); - continue; - } - - // load all materials of the mtl file into a vector - vector vmtl; - if(!read_materials(mfile, &vmtl)) { - continue; - } - fclose(mfile); - - // and add them all to the scene - for(size_t i=0; imatid = matnames[obj.cur_mat]; - add_mesh(mesh); - obj_added++; - } - - return obj_added > 0; -} - -static Mesh *cons_mesh(obj_file *obj) -{ - Mesh *mesh; - - // need at least one of each element - bool added_norm = false, added_tc = false; - if(obj->vn.empty()) { - obj->vn.push_back(Vector3(0, 0, 0)); - added_norm = true; - } - if(obj->vt.empty()) { - obj->vt.push_back(Vector3(0, 0, 0)); - added_tc = true; - } - - mesh = new Mesh; - - for(size_t i=0; if.size(); i++) { - Face face; - Vector3 v[3]; - - for(int j=0; j<3; j++) { - obj_face *f = &obj->f[i]; - - face.v[j].pos[0] = v[j].x = obj->v[f->v[j]].x; - face.v[j].pos[1] = v[j].y = obj->v[f->v[j]].y; - face.v[j].pos[2] = v[j].z = obj->v[f->v[j]].z; - face.v[j].pos[3] = 0.0; - - int nidx = f->n[j] < 0 ? 0 : f->n[j]; - face.v[j].normal[0] = obj->vn[nidx].x; - face.v[j].normal[1] = obj->vn[nidx].y; - face.v[j].normal[2] = obj->vn[nidx].z; - face.v[j].normal[3] = 0.0; - - int tidx = f->t[j] < 0 ? 0 : f->t[j]; - face.v[j].tex[0] = obj->vt[tidx].x; - face.v[j].tex[1] = obj->vt[tidx].y; - } - - Vector3 a = v[1] - v[0]; - Vector3 b = v[2] - v[0]; - Vector3 n = cross(a, b); - n.normalize(); - - face.normal[0] = n.x; - face.normal[1] = n.y; - face.normal[2] = n.z; - face.normal[3] = 0.0; - - mesh->faces.push_back(face); - } - - if(added_norm) { - obj->vn.pop_back(); - } - if(added_tc) { - obj->vt.pop_back(); - } - - return mesh; -} - -static bool read_materials(FILE *fp, vector *vmtl) -{ - obj_mat mat; - - for(;;) { - char line[BUF_SZ]; - fgets(line, sizeof line, fp); - if(feof(fp)) { - break; - } - - char *tok; - if(!(tok = strtok(line, SEP))) { - continue; - } - - int cmd; - if((cmd = get_cmd(tok)) == -1) { - continue; - } - - switch(cmd) { - case CMD_NEWMTL: - // add the previous material, and start a new one - if(mat.name.length() > 0) { - printf("Adding material: %s\n", mat.name.c_str()); - vmtl->push_back(mat); - mat.reset(); - } - if((tok = strtok(0, SEP))) { - mat.name = tok; - } - break; - - case CMD_KA: - parse_color(&mat.ambient); - break; - - case CMD_KD: - parse_color(&mat.diffuse); - break; - - case CMD_KS: - parse_color(&mat.specular); - break; - - case CMD_KR: - if((tok = strtok(0, SEP)) && is_float(tok)) { - mat.refl = atof(tok); - } - break; - - case CMD_NS: - if((tok = strtok(0, SEP)) && is_float(tok)) { - mat.shininess = atof(tok); - } - break; - - case CMD_NI: - if((tok = strtok(0, SEP)) && is_float(tok)) { - mat.ior = atof(tok); - } - break; - - case CMD_D: - case CMD_TR: - { - Vector3 c; - if(parse_color(&c)) { - mat.alpha = cmd == CMD_D ? c.x : 1.0 - c.x; - } - } - break; - - case CMD_MAP_KD: - mat.tex_dif = parse_map(); - break; - - default: - break; - } - } - - if(mat.name.length() > 0) { - printf("Adding material: %s\n", mat.name.c_str()); - vmtl->push_back(mat); - } - return true; -} - -static int get_cmd(char *str) -{ - char *s = str; - while((*s = toupper(*s))) s++; - - for(int i=0; cmd_names[i]; i++) { - if(strcmp(str, cmd_names[i]) == 0) { - return i; - } - } - return CMD_UNK; -} - -static bool is_int(const char *str) -{ - char *tmp; - strtol(str, &tmp, 10); - return tmp != str; -} - -static bool is_float(const char *str) -{ - char *tmp; - strtod(str, &tmp); - return tmp != str; -} - -static bool parse_vec(Vector3 *vec) -{ - for(int i=0; i<3; i++) { - char *tok; - - if(!(tok = strtok(0, SEP)) || !is_float(tok)) { - if(i < 2) { - return false; - } - vec->z = 0.0; - } else { - float v = atof(tok); - - switch(i) { - case 0: - vec->x = v; - break; - case 1: - vec->y = v; - break; - case 2: - vec->z = v; - break; - } - } - } - return true; -} - -static bool parse_color(Vector3 *col) -{ - for(int i=0; i<3; i++) { - char *tok; - - if(!(tok = strtok(0, SEP)) || !is_float(tok)) { - col->y = col->z = col->x; - return i > 0 ? true : false; - } - - float v = atof(tok); - switch(i) { - case 0: - col->x = v; - break; - case 1: - col->y = v; - break; - case 2: - col->z = v; - break; - } - } - return true; -} - -static bool parse_face(obj_face *face) -{ - char *tok[] = {0, 0, 0, 0}; - face->elem = 0; - - for(int i=0; i<4; i++) { - if((!(tok[i] = strtok(0, SEP)) || !is_int(tok[i]))) { - if(i < 3) return false; // less than 3 verts? not a polygon - } else { - face->elem++; - } - } - - for(int i=0; i<4; i++) { - char *subtok = tok[i]; - - if(!subtok || !*subtok || !is_int(subtok)) { - if(i < 3) { - return false; - } - face->v[i] = INVALID_IDX; - } else { - face->v[i] = atoi(subtok); - if(face->v[i] > 0) face->v[i]--; /* convert to 0-based */ - } - - while(subtok && *subtok && *subtok != '/') { - subtok++; - } - if(subtok && *subtok && *++subtok && is_int(subtok)) { - face->t[i] = atoi(subtok); - if(face->t[i] > 0) face->t[i]--; /* convert to 0-based */ - } else { - face->t[i] = INVALID_IDX; - } - - while(subtok && *subtok && *subtok != '/') { - subtok++; - } - if(subtok && *subtok && *++subtok && is_int(subtok)) { - face->n[i] = atoi(subtok); - if(face->n[i] > 0) face->n[i]--; /* convert to 0-based */ - } else { - face->n[i] = INVALID_IDX; - } - } - - return true; -} - -static const char *parse_map() -{ - char *tok, *prev = 0; - - while((tok = strtok(0, SEP))) { - prev = tok; - } - - return prev ? prev : ""; -} - -static bool find_file(char *res, int sz, const char *fname, const char *path, const char *mode) -{ - FILE *fp; - const char *beg, *end; - int fnamelen = strlen(fname); - - beg = path; - while(beg && *beg) { - end = beg; - while(*end && *end != ':') { - end++; - } - - int res_len = end - beg; - char *pathname = (char*)alloca(res_len + fnamelen + 2); - memcpy(pathname, beg, res_len); - pathname[res_len] = 0; - if(res_len) { - strcat(pathname, "/"); - } - strcat(pathname, fname); - - if((fp = fopen(pathname, mode))) { - fclose(fp); - strncpy(res, pathname, sz); - return true; - } - - beg += res_len; - if(*beg == ':') beg++; - } - return false; -} - -static const char *dirname(const char *str) -{ - static char buf[PATH_MAX]; - - if(!str || !*str) { - strcpy(buf, "."); - } else { - strncpy(buf, str, PATH_MAX); - char *ptr = strrchr(buf, '/'); - - if(ptr && *ptr) { - *ptr = 0; - } else { - strcpy(buf, "."); - } - } - return buf; -} - -static Vector3 operator -(const Vector3 &a, const Vector3 &b) -{ - return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); -} - -static Vector3 cross(const Vector3 &a, const Vector3 &b) -{ - Vector3 res; - res.x = a.y * b.z - a.z * b.y; - res.y = a.z * b.x - a.x * b.z; - res.z = a.x * b.y - a.y * b.x; - return res; -} diff -r 6c44e4b1726d -r 51f115e337c2 src/scene.h --- a/src/scene.h Wed Aug 11 04:30:35 2010 +0100 +++ b/src/scene.h Fri Aug 13 18:20:45 2010 +0100 @@ -1,6 +1,7 @@ #ifndef MESH_H_ #define MESH_H_ +#include #include struct Vertex { @@ -31,7 +32,7 @@ int matid; }; -/*enum { +enum { KDAXIS_X, KDAXIS_Y, KDAXIS_Z @@ -46,13 +47,13 @@ struct KDNode { int axis; float pt; -};*/ +}; class Scene { public: std::vector meshes; std::vector matlib; - //std::vector kdtree; + std::vector kdtree; bool add_mesh(Mesh *m); int get_num_meshes() const; @@ -65,7 +66,7 @@ bool load(const char *fname); bool load(FILE *fp); - //void build_kdtree(); + void build_kdtree(); }; #endif /* MESH_H_ */ diff -r 6c44e4b1726d -r 51f115e337c2 src/scene_obj.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/scene_obj.cc Fri Aug 13 18:20:45 2010 +0100 @@ -0,0 +1,656 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "scene.h" +#include "vector.h" + +#ifndef PATH_MAX +#define PATH_MAX 512 +#endif + +#define COMMANDS \ + CMD(V), \ + CMD(VN), \ + CMD(VT), \ + CMD(F), \ + CMD(O), \ + CMD(G), \ + CMD(MTLLIB), \ + CMD(USEMTL), \ + CMD(NEWMTL), \ + CMD(KA), \ + CMD(KD), \ + CMD(KS), \ + CMD(KR), \ + CMD(NS), \ + CMD(NI), \ + CMD(D), \ + CMD(TR), \ + CMD(MAP_KD), \ + CMD(MAP_KS), \ + CMD(MAP_NS), \ + CMD(MAP_D), \ + CMD(REFL), \ + CMD(BUMP) + +#define CMD(x) CMD_##x +enum { + COMMANDS, + CMD_UNK +}; +#undef CMD + +#define CMD(x) #x +static const char *cmd_names[] = { + COMMANDS, + 0 +}; +#undef CMD + +struct obj_face { + int elem; + int v[4], n[4], t[4]; +}; + +struct obj_file { + std::string cur_obj, cur_mat; + std::vector v, vn, vt; + std::vector f; +}; + +struct obj_mat { + std::string name; // newmtl + Vector3 ambient, diffuse, specular; // Ka, Kd, Ks + float shininess; // Ns + float ior; // Ni + float alpha; // d, Tr + float refl; // Kr (my extesnsion) + + std::string tex_dif, tex_spec, tex_shin, tex_alpha; // map_Kd, map_Ks, map_Ns, map_d + std::string tex_refl; // refl -type sphere|cube file + std::string tex_bump; // bump + + obj_mat() { reset(); } + + void reset() { + ambient = diffuse = Vector3(0.5, 0.5, 0.5); + specular = Vector3(0.0, 0.0, 0.0); + name = tex_dif = tex_spec = tex_shin = tex_alpha = tex_refl = tex_bump = ""; + shininess = 0; + ior = alpha = 1; + refl = 0.0; + } +}; + +static bool read_materials(FILE *fp, std::vector *vmtl); +static Mesh *cons_mesh(obj_file *obj); + +static int get_cmd(char *str); +static bool is_int(const char *str); +static bool is_float(const char *str); +static bool parse_vec(Vector3 *vec); +static bool parse_color(Vector3 *col); +static bool parse_face(obj_face *face); +static const char *parse_map(); + +static bool find_file(char *res, int sz, const char *fname, const char *path = ".", const char *mode = "rb"); +static const char *dirname(const char *str); + +static std::map matnames; + +#define INVALID_IDX INT_MIN + +#define SEP " \t\n\r\v" +#define BUF_SZ 512 + + +bool Scene::load(const char *fname) +{ + FILE *fp; + + if(!(fp = fopen(fname, "rb"))) { + fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno)); + return false; + } + + bool res = load(fp); + fclose(fp); + return res; +} + +bool Scene::load(FILE *fp) +{ + static int seq; + char cur_name[16]; + + obj_file obj; + + sprintf(cur_name, "default%02d.obj", seq++); + obj.cur_obj = cur_name; + + int prev_cmd = 0, obj_added = 0; + for(;;) { + Vector3 vec; + obj_face face; + + char line[BUF_SZ]; + fgets(line, sizeof line, fp); + if(feof(fp)) { + break; + } + + char *tok; + if(!(tok = strtok(line, SEP))) { + continue; // ignore empty lines + } + + int cmd; + if((cmd = get_cmd(tok)) == -1) { + continue; // ignore unknown commands ... + } + + switch(cmd) { + case CMD_V: + if(!parse_vec(&vec)) { + continue; + } + obj.v.push_back(vec); + break; + + case CMD_VN: + if(!parse_vec(&vec)) { + continue; + } + obj.vn.push_back(vec); + break; + + case CMD_VT: + if(!parse_vec(&vec)) { + continue; + } + vec.y = 1.0 - vec.y; + obj.vt.push_back(vec); + break; + + case CMD_O: + case CMD_G: + if(prev_cmd == CMD_O || prev_cmd == CMD_G) { + break; // just in case we've got both of them in a row + } + /* if we have any previous data, group them up, add the object + * and continue with the new one... + */ + if(!obj.f.empty()) { + Mesh *mesh = cons_mesh(&obj); + mesh->matid = matnames[obj.cur_mat]; + add_mesh(mesh); + obj_added++; + + obj.f.clear(); // clean the face list + } + if((tok = strtok(0, SEP))) { + obj.cur_obj = tok; + } else { + sprintf(cur_name, "default%02d.obj", seq++); + obj.cur_obj = cur_name; + } + break; + + case CMD_MTLLIB: + if((tok = strtok(0, SEP))) { + char path[PATH_MAX]; + + sprintf(path, ".:%s", dirname(tok)); + if(!find_file(path, PATH_MAX, tok, path)) { + fprintf(stderr, "material library not found: %s\n", tok); + continue; + } + + FILE *mfile; + if(!(mfile = fopen(path, "rb"))) { + fprintf(stderr, "failed to open material library: %s\n", path); + continue; + } + + // load all materials of the mtl file into a vector + std::vector vmtl; + if(!read_materials(mfile, &vmtl)) { + continue; + } + fclose(mfile); + + // and add them all to the scene + for(size_t i=0; imatid = matnames[obj.cur_mat]; + add_mesh(mesh); + obj_added++; + } + + return obj_added > 0; +} + +static Mesh *cons_mesh(obj_file *obj) +{ + Mesh *mesh; + + // need at least one of each element + bool added_norm = false, added_tc = false; + if(obj->vn.empty()) { + obj->vn.push_back(Vector3(0, 0, 0)); + added_norm = true; + } + if(obj->vt.empty()) { + obj->vt.push_back(Vector3(0, 0, 0)); + added_tc = true; + } + + mesh = new Mesh; + + for(size_t i=0; if.size(); i++) { + Face face; + Vector3 v[3]; + + for(int j=0; j<3; j++) { + obj_face *f = &obj->f[i]; + + face.v[j].pos[0] = v[j].x = obj->v[f->v[j]].x; + face.v[j].pos[1] = v[j].y = obj->v[f->v[j]].y; + face.v[j].pos[2] = v[j].z = obj->v[f->v[j]].z; + face.v[j].pos[3] = 0.0; + + int nidx = f->n[j] < 0 ? 0 : f->n[j]; + face.v[j].normal[0] = obj->vn[nidx].x; + face.v[j].normal[1] = obj->vn[nidx].y; + face.v[j].normal[2] = obj->vn[nidx].z; + face.v[j].normal[3] = 0.0; + + int tidx = f->t[j] < 0 ? 0 : f->t[j]; + face.v[j].tex[0] = obj->vt[tidx].x; + face.v[j].tex[1] = obj->vt[tidx].y; + } + + Vector3 a = v[1] - v[0]; + Vector3 b = v[2] - v[0]; + Vector3 n = cross(a, b); + n.normalize(); + + face.normal[0] = n.x; + face.normal[1] = n.y; + face.normal[2] = n.z; + face.normal[3] = 0.0; + + mesh->faces.push_back(face); + } + + if(added_norm) { + obj->vn.pop_back(); + } + if(added_tc) { + obj->vt.pop_back(); + } + + return mesh; +} + +static bool read_materials(FILE *fp, std::vector *vmtl) +{ + obj_mat mat; + + for(;;) { + char line[BUF_SZ]; + fgets(line, sizeof line, fp); + if(feof(fp)) { + break; + } + + char *tok; + if(!(tok = strtok(line, SEP))) { + continue; + } + + int cmd; + if((cmd = get_cmd(tok)) == -1) { + continue; + } + + switch(cmd) { + case CMD_NEWMTL: + // add the previous material, and start a new one + if(mat.name.length() > 0) { + printf("Adding material: %s\n", mat.name.c_str()); + vmtl->push_back(mat); + mat.reset(); + } + if((tok = strtok(0, SEP))) { + mat.name = tok; + } + break; + + case CMD_KA: + parse_color(&mat.ambient); + break; + + case CMD_KD: + parse_color(&mat.diffuse); + break; + + case CMD_KS: + parse_color(&mat.specular); + break; + + case CMD_KR: + if((tok = strtok(0, SEP)) && is_float(tok)) { + mat.refl = atof(tok); + } + break; + + case CMD_NS: + if((tok = strtok(0, SEP)) && is_float(tok)) { + mat.shininess = atof(tok); + } + break; + + case CMD_NI: + if((tok = strtok(0, SEP)) && is_float(tok)) { + mat.ior = atof(tok); + } + break; + + case CMD_D: + case CMD_TR: + { + Vector3 c; + if(parse_color(&c)) { + mat.alpha = cmd == CMD_D ? c.x : 1.0 - c.x; + } + } + break; + + case CMD_MAP_KD: + mat.tex_dif = parse_map(); + break; + + default: + break; + } + } + + if(mat.name.length() > 0) { + printf("Adding material: %s\n", mat.name.c_str()); + vmtl->push_back(mat); + } + return true; +} + +static int get_cmd(char *str) +{ + char *s = str; + while((*s = toupper(*s))) s++; + + for(int i=0; cmd_names[i]; i++) { + if(strcmp(str, cmd_names[i]) == 0) { + return i; + } + } + return CMD_UNK; +} + +static bool is_int(const char *str) +{ + char *tmp; + strtol(str, &tmp, 10); + return tmp != str; +} + +static bool is_float(const char *str) +{ + char *tmp; + strtod(str, &tmp); + return tmp != str; +} + +static bool parse_vec(Vector3 *vec) +{ + for(int i=0; i<3; i++) { + char *tok; + + if(!(tok = strtok(0, SEP)) || !is_float(tok)) { + if(i < 2) { + return false; + } + vec->z = 0.0; + } else { + float v = atof(tok); + + switch(i) { + case 0: + vec->x = v; + break; + case 1: + vec->y = v; + break; + case 2: + vec->z = v; + break; + } + } + } + return true; +} + +static bool parse_color(Vector3 *col) +{ + for(int i=0; i<3; i++) { + char *tok; + + if(!(tok = strtok(0, SEP)) || !is_float(tok)) { + col->y = col->z = col->x; + return i > 0 ? true : false; + } + + float v = atof(tok); + switch(i) { + case 0: + col->x = v; + break; + case 1: + col->y = v; + break; + case 2: + col->z = v; + break; + } + } + return true; +} + +static bool parse_face(obj_face *face) +{ + char *tok[] = {0, 0, 0, 0}; + face->elem = 0; + + for(int i=0; i<4; i++) { + if((!(tok[i] = strtok(0, SEP)) || !is_int(tok[i]))) { + if(i < 3) return false; // less than 3 verts? not a polygon + } else { + face->elem++; + } + } + + for(int i=0; i<4; i++) { + char *subtok = tok[i]; + + if(!subtok || !*subtok || !is_int(subtok)) { + if(i < 3) { + return false; + } + face->v[i] = INVALID_IDX; + } else { + face->v[i] = atoi(subtok); + if(face->v[i] > 0) face->v[i]--; /* convert to 0-based */ + } + + while(subtok && *subtok && *subtok != '/') { + subtok++; + } + if(subtok && *subtok && *++subtok && is_int(subtok)) { + face->t[i] = atoi(subtok); + if(face->t[i] > 0) face->t[i]--; /* convert to 0-based */ + } else { + face->t[i] = INVALID_IDX; + } + + while(subtok && *subtok && *subtok != '/') { + subtok++; + } + if(subtok && *subtok && *++subtok && is_int(subtok)) { + face->n[i] = atoi(subtok); + if(face->n[i] > 0) face->n[i]--; /* convert to 0-based */ + } else { + face->n[i] = INVALID_IDX; + } + } + + return true; +} + +static const char *parse_map() +{ + char *tok, *prev = 0; + + while((tok = strtok(0, SEP))) { + prev = tok; + } + + return prev ? prev : ""; +} + +static bool find_file(char *res, int sz, const char *fname, const char *path, const char *mode) +{ + FILE *fp; + const char *beg, *end; + int fnamelen = strlen(fname); + + beg = path; + while(beg && *beg) { + end = beg; + while(*end && *end != ':') { + end++; + } + + int res_len = end - beg; + char *pathname = (char*)alloca(res_len + fnamelen + 2); + memcpy(pathname, beg, res_len); + pathname[res_len] = 0; + if(res_len) { + strcat(pathname, "/"); + } + strcat(pathname, fname); + + if((fp = fopen(pathname, mode))) { + fclose(fp); + strncpy(res, pathname, sz); + return true; + } + + beg += res_len; + if(*beg == ':') beg++; + } + return false; +} + +static const char *dirname(const char *str) +{ + static char buf[PATH_MAX]; + + if(!str || !*str) { + strcpy(buf, "."); + } else { + strncpy(buf, str, PATH_MAX); + char *ptr = strrchr(buf, '/'); + + if(ptr && *ptr) { + *ptr = 0; + } else { + strcpy(buf, "."); + } + } + return buf; +} diff -r 6c44e4b1726d -r 51f115e337c2 src/vector.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vector.cc Fri Aug 13 18:20:45 2010 +0100 @@ -0,0 +1,29 @@ +#include "vector.h" + +Vector2::Vector2() : x(0), y(0) {} + +Vector2::Vector2(float x, float y) +{ + this->x = x; + this->y = y; +} + + +Vector3::Vector3() : x(0), y(0), z(0) {} + +Vector3::Vector3(float x, float y, float z) +{ + this->x = x; + this->y = y; + this->z = z; +} + +void Vector3::normalize() +{ + float len = sqrt(x * x + y * y + z * z); + if(len != 0.0) { + x /= len; + y /= len; + z /= len; + } +} diff -r 6c44e4b1726d -r 51f115e337c2 src/vector.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vector.h Fri Aug 13 18:20:45 2010 +0100 @@ -0,0 +1,37 @@ +#ifndef VECTOR_H_ +#define VECTOR_H_ + +class Vector2 { +public: + float x, y; + + Vector2(); + Vector2(float x, float y); +}; + +class Vector3 { +public: + float x, y, z; + + Vector3(); + Vector3(float x, float y, float z); + + void normalize(); + inline float length(); + inline float lengthsq(); +}; + +inline Vector3 operator +(const Vector3 &a, const Vector3 &b); +inline Vector3 operator -(const Vector3 &a, const Vector3 &b); +inline Vector3 operator *(const Vector3 &a, const Vector3 &b); +inline Vector3 operator /(const Vector3 &a, const Vector3 &b); + +inline Vector3 operator -(const Vector3 &vec); +inline Vector3 operator *(const Vector3 &vec, float s); + +inline float dot(const Vector3 &a, const Vector3 &b); +inline Vector3 cross(const Vector3 &a, const Vector3 &b); + +#include "vector.inl" + +#endif /* VECTOR_H_ */ diff -r 6c44e4b1726d -r 51f115e337c2 src/vector.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vector.inl Fri Aug 13 18:20:45 2010 +0100 @@ -0,0 +1,53 @@ +#include + +inline float Vector3::length() +{ + return sqrt(x * x + y * y + z * z); +} + +inline float Vector3::lengthsq() +{ + return x * x + y * y + z * z; +} + +inline Vector3 operator +(const Vector3 &a, const Vector3 &b) +{ + return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); +} + +inline Vector3 operator -(const Vector3 &a, const Vector3 &b) +{ + return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); +} + +inline Vector3 operator *(const Vector3 &a, const Vector3 &b) +{ + return Vector3(a.x * b.x, a.y * b.y, a.z * b.z); +} + +inline Vector3 operator /(const Vector3 &a, const Vector3 &b) +{ + return Vector3(a.x / b.x, a.y / b.y, a.z / b.z); +} + + +inline Vector3 operator -(const Vector3 &vec) +{ + return Vector3(-vec.x, -vec.y, -vec.z); +} + +inline Vector3 operator *(const Vector3 &vec, float s) +{ + return Vector3(vec.x * s, vec.y * s, vec.z * s); +} + + +inline float dot(const Vector3 &a, const Vector3 &b) +{ + return a.x * b.x + a.y * b.y + a.z * b.z; +} + +inline Vector3 cross(const Vector3 &a, const Vector3 &b) +{ + return Vector3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); +}