clray
changeset 23:51f115e337c2
separated obj loading and vector class
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 13 Aug 2010 18:20:45 +0100 |
parents | 6c44e4b1726d |
children | 13091c00d7ca |
files | rt.cl src/scene.cc src/scene.h src/scene_obj.cc src/vector.cc src/vector.h src/vector.inl |
diffstat | 7 files changed, 781 insertions(+), 695 deletions(-) [+] |
line diff
1.1 --- a/rt.cl Wed Aug 11 04:30:35 2010 +0100 1.2 +++ b/rt.cl Fri Aug 13 18:20:45 2010 +0100 1.3 @@ -212,8 +212,7 @@ 1.4 1.5 float4 reflect(float4 v, float4 n) 1.6 { 1.7 - float4 res = 2.0f * dot(v, n) * n - v; 1.8 - return res; 1.9 + return 2.0f * dot(v, n) * n - v; 1.10 } 1.11 1.12 float4 transform(float4 v, global const float *xform)
2.1 --- a/src/scene.cc Wed Aug 11 04:30:35 2010 +0100 2.2 +++ b/src/scene.cc Fri Aug 13 18:20:45 2010 +0100 2.3 @@ -1,130 +1,6 @@ 2.4 -#include <stdio.h> 2.5 -#include <stdlib.h> 2.6 -#include <string.h> 2.7 #include <math.h> 2.8 -#include <errno.h> 2.9 -#include <limits.h> 2.10 -#include <string> 2.11 -#include <vector> 2.12 -#include <map> 2.13 #include "scene.h" 2.14 2.15 -#ifndef PATH_MAX 2.16 -#define PATH_MAX 512 2.17 -#endif 2.18 - 2.19 -using namespace std; 2.20 - 2.21 -#define COMMANDS \ 2.22 - CMD(V), \ 2.23 - CMD(VN), \ 2.24 - CMD(VT), \ 2.25 - CMD(F), \ 2.26 - CMD(O), \ 2.27 - CMD(G), \ 2.28 - CMD(MTLLIB), \ 2.29 - CMD(USEMTL), \ 2.30 - CMD(NEWMTL), \ 2.31 - CMD(KA), \ 2.32 - CMD(KD), \ 2.33 - CMD(KS), \ 2.34 - CMD(KR), \ 2.35 - CMD(NS), \ 2.36 - CMD(NI), \ 2.37 - CMD(D), \ 2.38 - CMD(TR), \ 2.39 - CMD(MAP_KD), \ 2.40 - CMD(MAP_KS), \ 2.41 - CMD(MAP_NS), \ 2.42 - CMD(MAP_D), \ 2.43 - CMD(REFL), \ 2.44 - CMD(BUMP) 2.45 - 2.46 -#define CMD(x) CMD_##x 2.47 -enum { 2.48 - COMMANDS, 2.49 - CMD_UNK 2.50 -}; 2.51 -#undef CMD 2.52 - 2.53 -#define CMD(x) #x 2.54 -static const char *cmd_names[] = { 2.55 - COMMANDS, 2.56 - 0 2.57 -}; 2.58 -#undef CMD 2.59 - 2.60 -struct Vector3 { 2.61 - float x, y, z; 2.62 - 2.63 - Vector3() { x = y = z = 0.0; } 2.64 - Vector3(float a, float b, float c) { x = a; y = b; z = c; } 2.65 - 2.66 - void normalize() { float len = sqrt(x * x + y * y + z * z); x /= len; y /= len; z /= len; } 2.67 -}; 2.68 - 2.69 -struct Vector2 { 2.70 - float x, y; 2.71 - 2.72 - Vector2() { x = y = 0.0; } 2.73 - Vector2(float a, float b) { x = a; y = b; } 2.74 -}; 2.75 - 2.76 -struct obj_face { 2.77 - int elem; 2.78 - int v[4], n[4], t[4]; 2.79 -}; 2.80 - 2.81 -struct obj_file { 2.82 - string cur_obj, cur_mat; 2.83 - vector<Vector3> v, vn, vt; 2.84 - vector<obj_face> f; 2.85 -}; 2.86 - 2.87 -struct obj_mat { 2.88 - string name; // newmtl <name> 2.89 - Vector3 ambient, diffuse, specular; // Ka, Kd, Ks 2.90 - float shininess; // Ns 2.91 - float ior; // Ni 2.92 - float alpha; // d, Tr 2.93 - float refl; // Kr (my extesnsion) 2.94 - 2.95 - string tex_dif, tex_spec, tex_shin, tex_alpha; // map_Kd, map_Ks, map_Ns, map_d 2.96 - string tex_refl; // refl -type sphere|cube file 2.97 - string tex_bump; // bump 2.98 - 2.99 - obj_mat() { reset(); } 2.100 - 2.101 - void reset() { 2.102 - ambient = diffuse = Vector3(0.5, 0.5, 0.5); 2.103 - specular = Vector3(0.0, 0.0, 0.0); 2.104 - name = tex_dif = tex_spec = tex_shin = tex_alpha = tex_refl = tex_bump = ""; 2.105 - shininess = 0; 2.106 - ior = alpha = 1; 2.107 - refl = 0.0; 2.108 - } 2.109 -}; 2.110 - 2.111 -static bool read_materials(FILE *fp, vector<obj_mat> *vmtl); 2.112 -static Mesh *cons_mesh(obj_file *obj); 2.113 - 2.114 -static int get_cmd(char *str); 2.115 -static bool is_int(const char *str); 2.116 -static bool is_float(const char *str); 2.117 -static bool parse_vec(Vector3 *vec); 2.118 -static bool parse_color(Vector3 *col); 2.119 -static bool parse_face(obj_face *face); 2.120 -static const char *parse_map(); 2.121 - 2.122 -static bool find_file(char *res, int sz, const char *fname, const char *path = ".", const char *mode = "rb"); 2.123 -static const char *dirname(const char *str); 2.124 - 2.125 -static Vector3 operator -(const Vector3 &a, const Vector3 &b); 2.126 -static Vector3 cross(const Vector3 &a, const Vector3 &b); 2.127 - 2.128 -static map<string, int> matnames; 2.129 - 2.130 - 2.131 #define FEQ(a, b) (fabs((a) - (b)) < 1e-8) 2.132 bool Face::operator ==(const Face &f) const 2.133 { 2.134 @@ -188,568 +64,3 @@ 2.135 } 2.136 return &matlib[0]; 2.137 } 2.138 - 2.139 - 2.140 -#define INVALID_IDX INT_MIN 2.141 - 2.142 -#define SEP " \t\n\r\v" 2.143 -#define BUF_SZ 512 2.144 - 2.145 -bool Scene::load(const char *fname) 2.146 -{ 2.147 - FILE *fp; 2.148 - 2.149 - if(!(fp = fopen(fname, "rb"))) { 2.150 - fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno)); 2.151 - return false; 2.152 - } 2.153 - 2.154 - bool res = load(fp); 2.155 - fclose(fp); 2.156 - return res; 2.157 -} 2.158 - 2.159 -bool Scene::load(FILE *fp) 2.160 -{ 2.161 - static int seq; 2.162 - char cur_name[16]; 2.163 - 2.164 - obj_file obj; 2.165 - 2.166 - sprintf(cur_name, "default%02d.obj", seq++); 2.167 - obj.cur_obj = cur_name; 2.168 - 2.169 - int prev_cmd = 0, obj_added = 0; 2.170 - for(;;) { 2.171 - Vector3 vec; 2.172 - obj_face face; 2.173 - 2.174 - char line[BUF_SZ]; 2.175 - fgets(line, sizeof line, fp); 2.176 - if(feof(fp)) { 2.177 - break; 2.178 - } 2.179 - 2.180 - char *tok; 2.181 - if(!(tok = strtok(line, SEP))) { 2.182 - continue; // ignore empty lines 2.183 - } 2.184 - 2.185 - int cmd; 2.186 - if((cmd = get_cmd(tok)) == -1) { 2.187 - continue; // ignore unknown commands ... 2.188 - } 2.189 - 2.190 - switch(cmd) { 2.191 - case CMD_V: 2.192 - if(!parse_vec(&vec)) { 2.193 - continue; 2.194 - } 2.195 - obj.v.push_back(vec); 2.196 - break; 2.197 - 2.198 - case CMD_VN: 2.199 - if(!parse_vec(&vec)) { 2.200 - continue; 2.201 - } 2.202 - obj.vn.push_back(vec); 2.203 - break; 2.204 - 2.205 - case CMD_VT: 2.206 - if(!parse_vec(&vec)) { 2.207 - continue; 2.208 - } 2.209 - vec.y = 1.0 - vec.y; 2.210 - obj.vt.push_back(vec); 2.211 - break; 2.212 - 2.213 - case CMD_O: 2.214 - case CMD_G: 2.215 - if(prev_cmd == CMD_O || prev_cmd == CMD_G) { 2.216 - break; // just in case we've got both of them in a row 2.217 - } 2.218 - /* if we have any previous data, group them up, add the object 2.219 - * and continue with the new one... 2.220 - */ 2.221 - if(!obj.f.empty()) { 2.222 - Mesh *mesh = cons_mesh(&obj); 2.223 - mesh->matid = matnames[obj.cur_mat]; 2.224 - add_mesh(mesh); 2.225 - obj_added++; 2.226 - 2.227 - obj.f.clear(); // clean the face list 2.228 - } 2.229 - if((tok = strtok(0, SEP))) { 2.230 - obj.cur_obj = tok; 2.231 - } else { 2.232 - sprintf(cur_name, "default%02d.obj", seq++); 2.233 - obj.cur_obj = cur_name; 2.234 - } 2.235 - break; 2.236 - 2.237 - case CMD_MTLLIB: 2.238 - if((tok = strtok(0, SEP))) { 2.239 - char path[PATH_MAX]; 2.240 - 2.241 - sprintf(path, ".:%s", dirname(tok)); 2.242 - if(!find_file(path, PATH_MAX, tok, path)) { 2.243 - fprintf(stderr, "material library not found: %s\n", tok); 2.244 - continue; 2.245 - } 2.246 - 2.247 - FILE *mfile; 2.248 - if(!(mfile = fopen(path, "rb"))) { 2.249 - fprintf(stderr, "failed to open material library: %s\n", path); 2.250 - continue; 2.251 - } 2.252 - 2.253 - // load all materials of the mtl file into a vector 2.254 - vector<obj_mat> vmtl; 2.255 - if(!read_materials(mfile, &vmtl)) { 2.256 - continue; 2.257 - } 2.258 - fclose(mfile); 2.259 - 2.260 - // and add them all to the scene 2.261 - for(size_t i=0; i<vmtl.size(); i++) { 2.262 - Material mat; 2.263 - 2.264 - mat.kd[0] = vmtl[i].diffuse.x; 2.265 - mat.kd[1] = vmtl[i].diffuse.y; 2.266 - mat.kd[2] = vmtl[i].diffuse.z; 2.267 - 2.268 - mat.ks[0] = vmtl[i].specular.x; 2.269 - mat.ks[1] = vmtl[i].specular.y; 2.270 - mat.ks[2] = vmtl[i].specular.z; 2.271 - 2.272 - mat.kt = 1.0 - vmtl[i].alpha; 2.273 - mat.kr = vmtl[i].refl; 2.274 - mat.spow = vmtl[i].shininess; 2.275 - 2.276 - matlib.push_back(mat); 2.277 - matnames[vmtl[i].name] = i; 2.278 - } 2.279 - } 2.280 - break; 2.281 - 2.282 - case CMD_USEMTL: 2.283 - if((tok = strtok(0, SEP))) { 2.284 - obj.cur_mat = tok; 2.285 - } else { 2.286 - obj.cur_mat = ""; 2.287 - } 2.288 - break; 2.289 - 2.290 - case CMD_F: 2.291 - if(!parse_face(&face)) { 2.292 - continue; 2.293 - } 2.294 - 2.295 - // convert negative indices to regular indices 2.296 - for(int i=0; i<4; i++) { 2.297 - if(face.v[i] < 0 && face.v[i] != INVALID_IDX) { 2.298 - face.v[i] = obj.v.size() + face.v[i]; 2.299 - } 2.300 - if(face.n[i] < 0 && face.n[i] != INVALID_IDX) { 2.301 - face.n[i] = obj.vn.size() + face.n[i]; 2.302 - } 2.303 - if(face.t[i] < 0 && face.t[i] != INVALID_IDX) { 2.304 - face.t[i] = obj.vt.size() + face.t[i]; 2.305 - } 2.306 - } 2.307 - 2.308 - // break quads into triangles if needed 2.309 - obj.f.push_back(face); 2.310 - if(face.elem == 4) { 2.311 - face.v[1] = face.v[2]; 2.312 - face.n[1] = face.n[2]; 2.313 - face.t[1] = face.t[2]; 2.314 - 2.315 - face.v[2] = face.v[3]; 2.316 - face.n[2] = face.n[3]; 2.317 - face.t[2] = face.t[3]; 2.318 - 2.319 - obj.f.push_back(face); 2.320 - } 2.321 - break; 2.322 - 2.323 - default: 2.324 - break; // ignore unknown commands 2.325 - } 2.326 - 2.327 - prev_cmd = cmd; 2.328 - } 2.329 - 2.330 - // reached end of file... 2.331 - if(!obj.f.empty()) { 2.332 - Mesh *mesh = cons_mesh(&obj); 2.333 - mesh->matid = matnames[obj.cur_mat]; 2.334 - add_mesh(mesh); 2.335 - obj_added++; 2.336 - } 2.337 - 2.338 - return obj_added > 0; 2.339 -} 2.340 - 2.341 -static Mesh *cons_mesh(obj_file *obj) 2.342 -{ 2.343 - Mesh *mesh; 2.344 - 2.345 - // need at least one of each element 2.346 - bool added_norm = false, added_tc = false; 2.347 - if(obj->vn.empty()) { 2.348 - obj->vn.push_back(Vector3(0, 0, 0)); 2.349 - added_norm = true; 2.350 - } 2.351 - if(obj->vt.empty()) { 2.352 - obj->vt.push_back(Vector3(0, 0, 0)); 2.353 - added_tc = true; 2.354 - } 2.355 - 2.356 - mesh = new Mesh; 2.357 - 2.358 - for(size_t i=0; i<obj->f.size(); i++) { 2.359 - Face face; 2.360 - Vector3 v[3]; 2.361 - 2.362 - for(int j=0; j<3; j++) { 2.363 - obj_face *f = &obj->f[i]; 2.364 - 2.365 - face.v[j].pos[0] = v[j].x = obj->v[f->v[j]].x; 2.366 - face.v[j].pos[1] = v[j].y = obj->v[f->v[j]].y; 2.367 - face.v[j].pos[2] = v[j].z = obj->v[f->v[j]].z; 2.368 - face.v[j].pos[3] = 0.0; 2.369 - 2.370 - int nidx = f->n[j] < 0 ? 0 : f->n[j]; 2.371 - face.v[j].normal[0] = obj->vn[nidx].x; 2.372 - face.v[j].normal[1] = obj->vn[nidx].y; 2.373 - face.v[j].normal[2] = obj->vn[nidx].z; 2.374 - face.v[j].normal[3] = 0.0; 2.375 - 2.376 - int tidx = f->t[j] < 0 ? 0 : f->t[j]; 2.377 - face.v[j].tex[0] = obj->vt[tidx].x; 2.378 - face.v[j].tex[1] = obj->vt[tidx].y; 2.379 - } 2.380 - 2.381 - Vector3 a = v[1] - v[0]; 2.382 - Vector3 b = v[2] - v[0]; 2.383 - Vector3 n = cross(a, b); 2.384 - n.normalize(); 2.385 - 2.386 - face.normal[0] = n.x; 2.387 - face.normal[1] = n.y; 2.388 - face.normal[2] = n.z; 2.389 - face.normal[3] = 0.0; 2.390 - 2.391 - mesh->faces.push_back(face); 2.392 - } 2.393 - 2.394 - if(added_norm) { 2.395 - obj->vn.pop_back(); 2.396 - } 2.397 - if(added_tc) { 2.398 - obj->vt.pop_back(); 2.399 - } 2.400 - 2.401 - return mesh; 2.402 -} 2.403 - 2.404 -static bool read_materials(FILE *fp, vector<obj_mat> *vmtl) 2.405 -{ 2.406 - obj_mat mat; 2.407 - 2.408 - for(;;) { 2.409 - char line[BUF_SZ]; 2.410 - fgets(line, sizeof line, fp); 2.411 - if(feof(fp)) { 2.412 - break; 2.413 - } 2.414 - 2.415 - char *tok; 2.416 - if(!(tok = strtok(line, SEP))) { 2.417 - continue; 2.418 - } 2.419 - 2.420 - int cmd; 2.421 - if((cmd = get_cmd(tok)) == -1) { 2.422 - continue; 2.423 - } 2.424 - 2.425 - switch(cmd) { 2.426 - case CMD_NEWMTL: 2.427 - // add the previous material, and start a new one 2.428 - if(mat.name.length() > 0) { 2.429 - printf("Adding material: %s\n", mat.name.c_str()); 2.430 - vmtl->push_back(mat); 2.431 - mat.reset(); 2.432 - } 2.433 - if((tok = strtok(0, SEP))) { 2.434 - mat.name = tok; 2.435 - } 2.436 - break; 2.437 - 2.438 - case CMD_KA: 2.439 - parse_color(&mat.ambient); 2.440 - break; 2.441 - 2.442 - case CMD_KD: 2.443 - parse_color(&mat.diffuse); 2.444 - break; 2.445 - 2.446 - case CMD_KS: 2.447 - parse_color(&mat.specular); 2.448 - break; 2.449 - 2.450 - case CMD_KR: 2.451 - if((tok = strtok(0, SEP)) && is_float(tok)) { 2.452 - mat.refl = atof(tok); 2.453 - } 2.454 - break; 2.455 - 2.456 - case CMD_NS: 2.457 - if((tok = strtok(0, SEP)) && is_float(tok)) { 2.458 - mat.shininess = atof(tok); 2.459 - } 2.460 - break; 2.461 - 2.462 - case CMD_NI: 2.463 - if((tok = strtok(0, SEP)) && is_float(tok)) { 2.464 - mat.ior = atof(tok); 2.465 - } 2.466 - break; 2.467 - 2.468 - case CMD_D: 2.469 - case CMD_TR: 2.470 - { 2.471 - Vector3 c; 2.472 - if(parse_color(&c)) { 2.473 - mat.alpha = cmd == CMD_D ? c.x : 1.0 - c.x; 2.474 - } 2.475 - } 2.476 - break; 2.477 - 2.478 - case CMD_MAP_KD: 2.479 - mat.tex_dif = parse_map(); 2.480 - break; 2.481 - 2.482 - default: 2.483 - break; 2.484 - } 2.485 - } 2.486 - 2.487 - if(mat.name.length() > 0) { 2.488 - printf("Adding material: %s\n", mat.name.c_str()); 2.489 - vmtl->push_back(mat); 2.490 - } 2.491 - return true; 2.492 -} 2.493 - 2.494 -static int get_cmd(char *str) 2.495 -{ 2.496 - char *s = str; 2.497 - while((*s = toupper(*s))) s++; 2.498 - 2.499 - for(int i=0; cmd_names[i]; i++) { 2.500 - if(strcmp(str, cmd_names[i]) == 0) { 2.501 - return i; 2.502 - } 2.503 - } 2.504 - return CMD_UNK; 2.505 -} 2.506 - 2.507 -static bool is_int(const char *str) 2.508 -{ 2.509 - char *tmp; 2.510 - strtol(str, &tmp, 10); 2.511 - return tmp != str; 2.512 -} 2.513 - 2.514 -static bool is_float(const char *str) 2.515 -{ 2.516 - char *tmp; 2.517 - strtod(str, &tmp); 2.518 - return tmp != str; 2.519 -} 2.520 - 2.521 -static bool parse_vec(Vector3 *vec) 2.522 -{ 2.523 - for(int i=0; i<3; i++) { 2.524 - char *tok; 2.525 - 2.526 - if(!(tok = strtok(0, SEP)) || !is_float(tok)) { 2.527 - if(i < 2) { 2.528 - return false; 2.529 - } 2.530 - vec->z = 0.0; 2.531 - } else { 2.532 - float v = atof(tok); 2.533 - 2.534 - switch(i) { 2.535 - case 0: 2.536 - vec->x = v; 2.537 - break; 2.538 - case 1: 2.539 - vec->y = v; 2.540 - break; 2.541 - case 2: 2.542 - vec->z = v; 2.543 - break; 2.544 - } 2.545 - } 2.546 - } 2.547 - return true; 2.548 -} 2.549 - 2.550 -static bool parse_color(Vector3 *col) 2.551 -{ 2.552 - for(int i=0; i<3; i++) { 2.553 - char *tok; 2.554 - 2.555 - if(!(tok = strtok(0, SEP)) || !is_float(tok)) { 2.556 - col->y = col->z = col->x; 2.557 - return i > 0 ? true : false; 2.558 - } 2.559 - 2.560 - float v = atof(tok); 2.561 - switch(i) { 2.562 - case 0: 2.563 - col->x = v; 2.564 - break; 2.565 - case 1: 2.566 - col->y = v; 2.567 - break; 2.568 - case 2: 2.569 - col->z = v; 2.570 - break; 2.571 - } 2.572 - } 2.573 - return true; 2.574 -} 2.575 - 2.576 -static bool parse_face(obj_face *face) 2.577 -{ 2.578 - char *tok[] = {0, 0, 0, 0}; 2.579 - face->elem = 0; 2.580 - 2.581 - for(int i=0; i<4; i++) { 2.582 - if((!(tok[i] = strtok(0, SEP)) || !is_int(tok[i]))) { 2.583 - if(i < 3) return false; // less than 3 verts? not a polygon 2.584 - } else { 2.585 - face->elem++; 2.586 - } 2.587 - } 2.588 - 2.589 - for(int i=0; i<4; i++) { 2.590 - char *subtok = tok[i]; 2.591 - 2.592 - if(!subtok || !*subtok || !is_int(subtok)) { 2.593 - if(i < 3) { 2.594 - return false; 2.595 - } 2.596 - face->v[i] = INVALID_IDX; 2.597 - } else { 2.598 - face->v[i] = atoi(subtok); 2.599 - if(face->v[i] > 0) face->v[i]--; /* convert to 0-based */ 2.600 - } 2.601 - 2.602 - while(subtok && *subtok && *subtok != '/') { 2.603 - subtok++; 2.604 - } 2.605 - if(subtok && *subtok && *++subtok && is_int(subtok)) { 2.606 - face->t[i] = atoi(subtok); 2.607 - if(face->t[i] > 0) face->t[i]--; /* convert to 0-based */ 2.608 - } else { 2.609 - face->t[i] = INVALID_IDX; 2.610 - } 2.611 - 2.612 - while(subtok && *subtok && *subtok != '/') { 2.613 - subtok++; 2.614 - } 2.615 - if(subtok && *subtok && *++subtok && is_int(subtok)) { 2.616 - face->n[i] = atoi(subtok); 2.617 - if(face->n[i] > 0) face->n[i]--; /* convert to 0-based */ 2.618 - } else { 2.619 - face->n[i] = INVALID_IDX; 2.620 - } 2.621 - } 2.622 - 2.623 - return true; 2.624 -} 2.625 - 2.626 -static const char *parse_map() 2.627 -{ 2.628 - char *tok, *prev = 0; 2.629 - 2.630 - while((tok = strtok(0, SEP))) { 2.631 - prev = tok; 2.632 - } 2.633 - 2.634 - return prev ? prev : ""; 2.635 -} 2.636 - 2.637 -static bool find_file(char *res, int sz, const char *fname, const char *path, const char *mode) 2.638 -{ 2.639 - FILE *fp; 2.640 - const char *beg, *end; 2.641 - int fnamelen = strlen(fname); 2.642 - 2.643 - beg = path; 2.644 - while(beg && *beg) { 2.645 - end = beg; 2.646 - while(*end && *end != ':') { 2.647 - end++; 2.648 - } 2.649 - 2.650 - int res_len = end - beg; 2.651 - char *pathname = (char*)alloca(res_len + fnamelen + 2); 2.652 - memcpy(pathname, beg, res_len); 2.653 - pathname[res_len] = 0; 2.654 - if(res_len) { 2.655 - strcat(pathname, "/"); 2.656 - } 2.657 - strcat(pathname, fname); 2.658 - 2.659 - if((fp = fopen(pathname, mode))) { 2.660 - fclose(fp); 2.661 - strncpy(res, pathname, sz); 2.662 - return true; 2.663 - } 2.664 - 2.665 - beg += res_len; 2.666 - if(*beg == ':') beg++; 2.667 - } 2.668 - return false; 2.669 -} 2.670 - 2.671 -static const char *dirname(const char *str) 2.672 -{ 2.673 - static char buf[PATH_MAX]; 2.674 - 2.675 - if(!str || !*str) { 2.676 - strcpy(buf, "."); 2.677 - } else { 2.678 - strncpy(buf, str, PATH_MAX); 2.679 - char *ptr = strrchr(buf, '/'); 2.680 - 2.681 - if(ptr && *ptr) { 2.682 - *ptr = 0; 2.683 - } else { 2.684 - strcpy(buf, "."); 2.685 - } 2.686 - } 2.687 - return buf; 2.688 -} 2.689 - 2.690 -static Vector3 operator -(const Vector3 &a, const Vector3 &b) 2.691 -{ 2.692 - return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); 2.693 -} 2.694 - 2.695 -static Vector3 cross(const Vector3 &a, const Vector3 &b) 2.696 -{ 2.697 - Vector3 res; 2.698 - res.x = a.y * b.z - a.z * b.y; 2.699 - res.y = a.z * b.x - a.x * b.z; 2.700 - res.z = a.x * b.y - a.y * b.x; 2.701 - return res; 2.702 -}
3.1 --- a/src/scene.h Wed Aug 11 04:30:35 2010 +0100 3.2 +++ b/src/scene.h Fri Aug 13 18:20:45 2010 +0100 3.3 @@ -1,6 +1,7 @@ 3.4 #ifndef MESH_H_ 3.5 #define MESH_H_ 3.6 3.7 +#include <stdio.h> 3.8 #include <vector> 3.9 3.10 struct Vertex { 3.11 @@ -31,7 +32,7 @@ 3.12 int matid; 3.13 }; 3.14 3.15 -/*enum { 3.16 +enum { 3.17 KDAXIS_X, 3.18 KDAXIS_Y, 3.19 KDAXIS_Z 3.20 @@ -46,13 +47,13 @@ 3.21 struct KDNode { 3.22 int axis; 3.23 float pt; 3.24 -};*/ 3.25 +}; 3.26 3.27 class Scene { 3.28 public: 3.29 std::vector<Mesh*> meshes; 3.30 std::vector<Material> matlib; 3.31 - //std::vector<KDNode> kdtree; 3.32 + std::vector<KDNode> kdtree; 3.33 3.34 bool add_mesh(Mesh *m); 3.35 int get_num_meshes() const; 3.36 @@ -65,7 +66,7 @@ 3.37 bool load(const char *fname); 3.38 bool load(FILE *fp); 3.39 3.40 - //void build_kdtree(); 3.41 + void build_kdtree(); 3.42 }; 3.43 3.44 #endif /* MESH_H_ */
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/scene_obj.cc Fri Aug 13 18:20:45 2010 +0100 4.3 @@ -0,0 +1,656 @@ 4.4 +#include <stdio.h> 4.5 +#include <stdlib.h> 4.6 +#include <string.h> 4.7 +#include <errno.h> 4.8 +#include <ctype.h> 4.9 +#include <limits.h> 4.10 +#include <string> 4.11 +#include <vector> 4.12 +#include <map> 4.13 +#include "scene.h" 4.14 +#include "vector.h" 4.15 + 4.16 +#ifndef PATH_MAX 4.17 +#define PATH_MAX 512 4.18 +#endif 4.19 + 4.20 +#define COMMANDS \ 4.21 + CMD(V), \ 4.22 + CMD(VN), \ 4.23 + CMD(VT), \ 4.24 + CMD(F), \ 4.25 + CMD(O), \ 4.26 + CMD(G), \ 4.27 + CMD(MTLLIB), \ 4.28 + CMD(USEMTL), \ 4.29 + CMD(NEWMTL), \ 4.30 + CMD(KA), \ 4.31 + CMD(KD), \ 4.32 + CMD(KS), \ 4.33 + CMD(KR), \ 4.34 + CMD(NS), \ 4.35 + CMD(NI), \ 4.36 + CMD(D), \ 4.37 + CMD(TR), \ 4.38 + CMD(MAP_KD), \ 4.39 + CMD(MAP_KS), \ 4.40 + CMD(MAP_NS), \ 4.41 + CMD(MAP_D), \ 4.42 + CMD(REFL), \ 4.43 + CMD(BUMP) 4.44 + 4.45 +#define CMD(x) CMD_##x 4.46 +enum { 4.47 + COMMANDS, 4.48 + CMD_UNK 4.49 +}; 4.50 +#undef CMD 4.51 + 4.52 +#define CMD(x) #x 4.53 +static const char *cmd_names[] = { 4.54 + COMMANDS, 4.55 + 0 4.56 +}; 4.57 +#undef CMD 4.58 + 4.59 +struct obj_face { 4.60 + int elem; 4.61 + int v[4], n[4], t[4]; 4.62 +}; 4.63 + 4.64 +struct obj_file { 4.65 + std::string cur_obj, cur_mat; 4.66 + std::vector<Vector3> v, vn, vt; 4.67 + std::vector<obj_face> f; 4.68 +}; 4.69 + 4.70 +struct obj_mat { 4.71 + std::string name; // newmtl <name> 4.72 + Vector3 ambient, diffuse, specular; // Ka, Kd, Ks 4.73 + float shininess; // Ns 4.74 + float ior; // Ni 4.75 + float alpha; // d, Tr 4.76 + float refl; // Kr (my extesnsion) 4.77 + 4.78 + std::string tex_dif, tex_spec, tex_shin, tex_alpha; // map_Kd, map_Ks, map_Ns, map_d 4.79 + std::string tex_refl; // refl -type sphere|cube file 4.80 + std::string tex_bump; // bump 4.81 + 4.82 + obj_mat() { reset(); } 4.83 + 4.84 + void reset() { 4.85 + ambient = diffuse = Vector3(0.5, 0.5, 0.5); 4.86 + specular = Vector3(0.0, 0.0, 0.0); 4.87 + name = tex_dif = tex_spec = tex_shin = tex_alpha = tex_refl = tex_bump = ""; 4.88 + shininess = 0; 4.89 + ior = alpha = 1; 4.90 + refl = 0.0; 4.91 + } 4.92 +}; 4.93 + 4.94 +static bool read_materials(FILE *fp, std::vector<obj_mat> *vmtl); 4.95 +static Mesh *cons_mesh(obj_file *obj); 4.96 + 4.97 +static int get_cmd(char *str); 4.98 +static bool is_int(const char *str); 4.99 +static bool is_float(const char *str); 4.100 +static bool parse_vec(Vector3 *vec); 4.101 +static bool parse_color(Vector3 *col); 4.102 +static bool parse_face(obj_face *face); 4.103 +static const char *parse_map(); 4.104 + 4.105 +static bool find_file(char *res, int sz, const char *fname, const char *path = ".", const char *mode = "rb"); 4.106 +static const char *dirname(const char *str); 4.107 + 4.108 +static std::map<std::string, int> matnames; 4.109 + 4.110 +#define INVALID_IDX INT_MIN 4.111 + 4.112 +#define SEP " \t\n\r\v" 4.113 +#define BUF_SZ 512 4.114 + 4.115 + 4.116 +bool Scene::load(const char *fname) 4.117 +{ 4.118 + FILE *fp; 4.119 + 4.120 + if(!(fp = fopen(fname, "rb"))) { 4.121 + fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno)); 4.122 + return false; 4.123 + } 4.124 + 4.125 + bool res = load(fp); 4.126 + fclose(fp); 4.127 + return res; 4.128 +} 4.129 + 4.130 +bool Scene::load(FILE *fp) 4.131 +{ 4.132 + static int seq; 4.133 + char cur_name[16]; 4.134 + 4.135 + obj_file obj; 4.136 + 4.137 + sprintf(cur_name, "default%02d.obj", seq++); 4.138 + obj.cur_obj = cur_name; 4.139 + 4.140 + int prev_cmd = 0, obj_added = 0; 4.141 + for(;;) { 4.142 + Vector3 vec; 4.143 + obj_face face; 4.144 + 4.145 + char line[BUF_SZ]; 4.146 + fgets(line, sizeof line, fp); 4.147 + if(feof(fp)) { 4.148 + break; 4.149 + } 4.150 + 4.151 + char *tok; 4.152 + if(!(tok = strtok(line, SEP))) { 4.153 + continue; // ignore empty lines 4.154 + } 4.155 + 4.156 + int cmd; 4.157 + if((cmd = get_cmd(tok)) == -1) { 4.158 + continue; // ignore unknown commands ... 4.159 + } 4.160 + 4.161 + switch(cmd) { 4.162 + case CMD_V: 4.163 + if(!parse_vec(&vec)) { 4.164 + continue; 4.165 + } 4.166 + obj.v.push_back(vec); 4.167 + break; 4.168 + 4.169 + case CMD_VN: 4.170 + if(!parse_vec(&vec)) { 4.171 + continue; 4.172 + } 4.173 + obj.vn.push_back(vec); 4.174 + break; 4.175 + 4.176 + case CMD_VT: 4.177 + if(!parse_vec(&vec)) { 4.178 + continue; 4.179 + } 4.180 + vec.y = 1.0 - vec.y; 4.181 + obj.vt.push_back(vec); 4.182 + break; 4.183 + 4.184 + case CMD_O: 4.185 + case CMD_G: 4.186 + if(prev_cmd == CMD_O || prev_cmd == CMD_G) { 4.187 + break; // just in case we've got both of them in a row 4.188 + } 4.189 + /* if we have any previous data, group them up, add the object 4.190 + * and continue with the new one... 4.191 + */ 4.192 + if(!obj.f.empty()) { 4.193 + Mesh *mesh = cons_mesh(&obj); 4.194 + mesh->matid = matnames[obj.cur_mat]; 4.195 + add_mesh(mesh); 4.196 + obj_added++; 4.197 + 4.198 + obj.f.clear(); // clean the face list 4.199 + } 4.200 + if((tok = strtok(0, SEP))) { 4.201 + obj.cur_obj = tok; 4.202 + } else { 4.203 + sprintf(cur_name, "default%02d.obj", seq++); 4.204 + obj.cur_obj = cur_name; 4.205 + } 4.206 + break; 4.207 + 4.208 + case CMD_MTLLIB: 4.209 + if((tok = strtok(0, SEP))) { 4.210 + char path[PATH_MAX]; 4.211 + 4.212 + sprintf(path, ".:%s", dirname(tok)); 4.213 + if(!find_file(path, PATH_MAX, tok, path)) { 4.214 + fprintf(stderr, "material library not found: %s\n", tok); 4.215 + continue; 4.216 + } 4.217 + 4.218 + FILE *mfile; 4.219 + if(!(mfile = fopen(path, "rb"))) { 4.220 + fprintf(stderr, "failed to open material library: %s\n", path); 4.221 + continue; 4.222 + } 4.223 + 4.224 + // load all materials of the mtl file into a vector 4.225 + std::vector<obj_mat> vmtl; 4.226 + if(!read_materials(mfile, &vmtl)) { 4.227 + continue; 4.228 + } 4.229 + fclose(mfile); 4.230 + 4.231 + // and add them all to the scene 4.232 + for(size_t i=0; i<vmtl.size(); i++) { 4.233 + Material mat; 4.234 + 4.235 + mat.kd[0] = vmtl[i].diffuse.x; 4.236 + mat.kd[1] = vmtl[i].diffuse.y; 4.237 + mat.kd[2] = vmtl[i].diffuse.z; 4.238 + 4.239 + mat.ks[0] = vmtl[i].specular.x; 4.240 + mat.ks[1] = vmtl[i].specular.y; 4.241 + mat.ks[2] = vmtl[i].specular.z; 4.242 + 4.243 + mat.kt = 1.0 - vmtl[i].alpha; 4.244 + mat.kr = vmtl[i].refl; 4.245 + mat.spow = vmtl[i].shininess; 4.246 + 4.247 + matlib.push_back(mat); 4.248 + matnames[vmtl[i].name] = i; 4.249 + } 4.250 + } 4.251 + break; 4.252 + 4.253 + case CMD_USEMTL: 4.254 + if((tok = strtok(0, SEP))) { 4.255 + obj.cur_mat = tok; 4.256 + } else { 4.257 + obj.cur_mat = ""; 4.258 + } 4.259 + break; 4.260 + 4.261 + case CMD_F: 4.262 + if(!parse_face(&face)) { 4.263 + continue; 4.264 + } 4.265 + 4.266 + // convert negative indices to regular indices 4.267 + for(int i=0; i<4; i++) { 4.268 + if(face.v[i] < 0 && face.v[i] != INVALID_IDX) { 4.269 + face.v[i] = obj.v.size() + face.v[i]; 4.270 + } 4.271 + if(face.n[i] < 0 && face.n[i] != INVALID_IDX) { 4.272 + face.n[i] = obj.vn.size() + face.n[i]; 4.273 + } 4.274 + if(face.t[i] < 0 && face.t[i] != INVALID_IDX) { 4.275 + face.t[i] = obj.vt.size() + face.t[i]; 4.276 + } 4.277 + } 4.278 + 4.279 + // break quads into triangles if needed 4.280 + obj.f.push_back(face); 4.281 + if(face.elem == 4) { 4.282 + face.v[1] = face.v[2]; 4.283 + face.n[1] = face.n[2]; 4.284 + face.t[1] = face.t[2]; 4.285 + 4.286 + face.v[2] = face.v[3]; 4.287 + face.n[2] = face.n[3]; 4.288 + face.t[2] = face.t[3]; 4.289 + 4.290 + obj.f.push_back(face); 4.291 + } 4.292 + break; 4.293 + 4.294 + default: 4.295 + break; // ignore unknown commands 4.296 + } 4.297 + 4.298 + prev_cmd = cmd; 4.299 + } 4.300 + 4.301 + // reached end of file... 4.302 + if(!obj.f.empty()) { 4.303 + Mesh *mesh = cons_mesh(&obj); 4.304 + mesh->matid = matnames[obj.cur_mat]; 4.305 + add_mesh(mesh); 4.306 + obj_added++; 4.307 + } 4.308 + 4.309 + return obj_added > 0; 4.310 +} 4.311 + 4.312 +static Mesh *cons_mesh(obj_file *obj) 4.313 +{ 4.314 + Mesh *mesh; 4.315 + 4.316 + // need at least one of each element 4.317 + bool added_norm = false, added_tc = false; 4.318 + if(obj->vn.empty()) { 4.319 + obj->vn.push_back(Vector3(0, 0, 0)); 4.320 + added_norm = true; 4.321 + } 4.322 + if(obj->vt.empty()) { 4.323 + obj->vt.push_back(Vector3(0, 0, 0)); 4.324 + added_tc = true; 4.325 + } 4.326 + 4.327 + mesh = new Mesh; 4.328 + 4.329 + for(size_t i=0; i<obj->f.size(); i++) { 4.330 + Face face; 4.331 + Vector3 v[3]; 4.332 + 4.333 + for(int j=0; j<3; j++) { 4.334 + obj_face *f = &obj->f[i]; 4.335 + 4.336 + face.v[j].pos[0] = v[j].x = obj->v[f->v[j]].x; 4.337 + face.v[j].pos[1] = v[j].y = obj->v[f->v[j]].y; 4.338 + face.v[j].pos[2] = v[j].z = obj->v[f->v[j]].z; 4.339 + face.v[j].pos[3] = 0.0; 4.340 + 4.341 + int nidx = f->n[j] < 0 ? 0 : f->n[j]; 4.342 + face.v[j].normal[0] = obj->vn[nidx].x; 4.343 + face.v[j].normal[1] = obj->vn[nidx].y; 4.344 + face.v[j].normal[2] = obj->vn[nidx].z; 4.345 + face.v[j].normal[3] = 0.0; 4.346 + 4.347 + int tidx = f->t[j] < 0 ? 0 : f->t[j]; 4.348 + face.v[j].tex[0] = obj->vt[tidx].x; 4.349 + face.v[j].tex[1] = obj->vt[tidx].y; 4.350 + } 4.351 + 4.352 + Vector3 a = v[1] - v[0]; 4.353 + Vector3 b = v[2] - v[0]; 4.354 + Vector3 n = cross(a, b); 4.355 + n.normalize(); 4.356 + 4.357 + face.normal[0] = n.x; 4.358 + face.normal[1] = n.y; 4.359 + face.normal[2] = n.z; 4.360 + face.normal[3] = 0.0; 4.361 + 4.362 + mesh->faces.push_back(face); 4.363 + } 4.364 + 4.365 + if(added_norm) { 4.366 + obj->vn.pop_back(); 4.367 + } 4.368 + if(added_tc) { 4.369 + obj->vt.pop_back(); 4.370 + } 4.371 + 4.372 + return mesh; 4.373 +} 4.374 + 4.375 +static bool read_materials(FILE *fp, std::vector<obj_mat> *vmtl) 4.376 +{ 4.377 + obj_mat mat; 4.378 + 4.379 + for(;;) { 4.380 + char line[BUF_SZ]; 4.381 + fgets(line, sizeof line, fp); 4.382 + if(feof(fp)) { 4.383 + break; 4.384 + } 4.385 + 4.386 + char *tok; 4.387 + if(!(tok = strtok(line, SEP))) { 4.388 + continue; 4.389 + } 4.390 + 4.391 + int cmd; 4.392 + if((cmd = get_cmd(tok)) == -1) { 4.393 + continue; 4.394 + } 4.395 + 4.396 + switch(cmd) { 4.397 + case CMD_NEWMTL: 4.398 + // add the previous material, and start a new one 4.399 + if(mat.name.length() > 0) { 4.400 + printf("Adding material: %s\n", mat.name.c_str()); 4.401 + vmtl->push_back(mat); 4.402 + mat.reset(); 4.403 + } 4.404 + if((tok = strtok(0, SEP))) { 4.405 + mat.name = tok; 4.406 + } 4.407 + break; 4.408 + 4.409 + case CMD_KA: 4.410 + parse_color(&mat.ambient); 4.411 + break; 4.412 + 4.413 + case CMD_KD: 4.414 + parse_color(&mat.diffuse); 4.415 + break; 4.416 + 4.417 + case CMD_KS: 4.418 + parse_color(&mat.specular); 4.419 + break; 4.420 + 4.421 + case CMD_KR: 4.422 + if((tok = strtok(0, SEP)) && is_float(tok)) { 4.423 + mat.refl = atof(tok); 4.424 + } 4.425 + break; 4.426 + 4.427 + case CMD_NS: 4.428 + if((tok = strtok(0, SEP)) && is_float(tok)) { 4.429 + mat.shininess = atof(tok); 4.430 + } 4.431 + break; 4.432 + 4.433 + case CMD_NI: 4.434 + if((tok = strtok(0, SEP)) && is_float(tok)) { 4.435 + mat.ior = atof(tok); 4.436 + } 4.437 + break; 4.438 + 4.439 + case CMD_D: 4.440 + case CMD_TR: 4.441 + { 4.442 + Vector3 c; 4.443 + if(parse_color(&c)) { 4.444 + mat.alpha = cmd == CMD_D ? c.x : 1.0 - c.x; 4.445 + } 4.446 + } 4.447 + break; 4.448 + 4.449 + case CMD_MAP_KD: 4.450 + mat.tex_dif = parse_map(); 4.451 + break; 4.452 + 4.453 + default: 4.454 + break; 4.455 + } 4.456 + } 4.457 + 4.458 + if(mat.name.length() > 0) { 4.459 + printf("Adding material: %s\n", mat.name.c_str()); 4.460 + vmtl->push_back(mat); 4.461 + } 4.462 + return true; 4.463 +} 4.464 + 4.465 +static int get_cmd(char *str) 4.466 +{ 4.467 + char *s = str; 4.468 + while((*s = toupper(*s))) s++; 4.469 + 4.470 + for(int i=0; cmd_names[i]; i++) { 4.471 + if(strcmp(str, cmd_names[i]) == 0) { 4.472 + return i; 4.473 + } 4.474 + } 4.475 + return CMD_UNK; 4.476 +} 4.477 + 4.478 +static bool is_int(const char *str) 4.479 +{ 4.480 + char *tmp; 4.481 + strtol(str, &tmp, 10); 4.482 + return tmp != str; 4.483 +} 4.484 + 4.485 +static bool is_float(const char *str) 4.486 +{ 4.487 + char *tmp; 4.488 + strtod(str, &tmp); 4.489 + return tmp != str; 4.490 +} 4.491 + 4.492 +static bool parse_vec(Vector3 *vec) 4.493 +{ 4.494 + for(int i=0; i<3; i++) { 4.495 + char *tok; 4.496 + 4.497 + if(!(tok = strtok(0, SEP)) || !is_float(tok)) { 4.498 + if(i < 2) { 4.499 + return false; 4.500 + } 4.501 + vec->z = 0.0; 4.502 + } else { 4.503 + float v = atof(tok); 4.504 + 4.505 + switch(i) { 4.506 + case 0: 4.507 + vec->x = v; 4.508 + break; 4.509 + case 1: 4.510 + vec->y = v; 4.511 + break; 4.512 + case 2: 4.513 + vec->z = v; 4.514 + break; 4.515 + } 4.516 + } 4.517 + } 4.518 + return true; 4.519 +} 4.520 + 4.521 +static bool parse_color(Vector3 *col) 4.522 +{ 4.523 + for(int i=0; i<3; i++) { 4.524 + char *tok; 4.525 + 4.526 + if(!(tok = strtok(0, SEP)) || !is_float(tok)) { 4.527 + col->y = col->z = col->x; 4.528 + return i > 0 ? true : false; 4.529 + } 4.530 + 4.531 + float v = atof(tok); 4.532 + switch(i) { 4.533 + case 0: 4.534 + col->x = v; 4.535 + break; 4.536 + case 1: 4.537 + col->y = v; 4.538 + break; 4.539 + case 2: 4.540 + col->z = v; 4.541 + break; 4.542 + } 4.543 + } 4.544 + return true; 4.545 +} 4.546 + 4.547 +static bool parse_face(obj_face *face) 4.548 +{ 4.549 + char *tok[] = {0, 0, 0, 0}; 4.550 + face->elem = 0; 4.551 + 4.552 + for(int i=0; i<4; i++) { 4.553 + if((!(tok[i] = strtok(0, SEP)) || !is_int(tok[i]))) { 4.554 + if(i < 3) return false; // less than 3 verts? not a polygon 4.555 + } else { 4.556 + face->elem++; 4.557 + } 4.558 + } 4.559 + 4.560 + for(int i=0; i<4; i++) { 4.561 + char *subtok = tok[i]; 4.562 + 4.563 + if(!subtok || !*subtok || !is_int(subtok)) { 4.564 + if(i < 3) { 4.565 + return false; 4.566 + } 4.567 + face->v[i] = INVALID_IDX; 4.568 + } else { 4.569 + face->v[i] = atoi(subtok); 4.570 + if(face->v[i] > 0) face->v[i]--; /* convert to 0-based */ 4.571 + } 4.572 + 4.573 + while(subtok && *subtok && *subtok != '/') { 4.574 + subtok++; 4.575 + } 4.576 + if(subtok && *subtok && *++subtok && is_int(subtok)) { 4.577 + face->t[i] = atoi(subtok); 4.578 + if(face->t[i] > 0) face->t[i]--; /* convert to 0-based */ 4.579 + } else { 4.580 + face->t[i] = INVALID_IDX; 4.581 + } 4.582 + 4.583 + while(subtok && *subtok && *subtok != '/') { 4.584 + subtok++; 4.585 + } 4.586 + if(subtok && *subtok && *++subtok && is_int(subtok)) { 4.587 + face->n[i] = atoi(subtok); 4.588 + if(face->n[i] > 0) face->n[i]--; /* convert to 0-based */ 4.589 + } else { 4.590 + face->n[i] = INVALID_IDX; 4.591 + } 4.592 + } 4.593 + 4.594 + return true; 4.595 +} 4.596 + 4.597 +static const char *parse_map() 4.598 +{ 4.599 + char *tok, *prev = 0; 4.600 + 4.601 + while((tok = strtok(0, SEP))) { 4.602 + prev = tok; 4.603 + } 4.604 + 4.605 + return prev ? prev : ""; 4.606 +} 4.607 + 4.608 +static bool find_file(char *res, int sz, const char *fname, const char *path, const char *mode) 4.609 +{ 4.610 + FILE *fp; 4.611 + const char *beg, *end; 4.612 + int fnamelen = strlen(fname); 4.613 + 4.614 + beg = path; 4.615 + while(beg && *beg) { 4.616 + end = beg; 4.617 + while(*end && *end != ':') { 4.618 + end++; 4.619 + } 4.620 + 4.621 + int res_len = end - beg; 4.622 + char *pathname = (char*)alloca(res_len + fnamelen + 2); 4.623 + memcpy(pathname, beg, res_len); 4.624 + pathname[res_len] = 0; 4.625 + if(res_len) { 4.626 + strcat(pathname, "/"); 4.627 + } 4.628 + strcat(pathname, fname); 4.629 + 4.630 + if((fp = fopen(pathname, mode))) { 4.631 + fclose(fp); 4.632 + strncpy(res, pathname, sz); 4.633 + return true; 4.634 + } 4.635 + 4.636 + beg += res_len; 4.637 + if(*beg == ':') beg++; 4.638 + } 4.639 + return false; 4.640 +} 4.641 + 4.642 +static const char *dirname(const char *str) 4.643 +{ 4.644 + static char buf[PATH_MAX]; 4.645 + 4.646 + if(!str || !*str) { 4.647 + strcpy(buf, "."); 4.648 + } else { 4.649 + strncpy(buf, str, PATH_MAX); 4.650 + char *ptr = strrchr(buf, '/'); 4.651 + 4.652 + if(ptr && *ptr) { 4.653 + *ptr = 0; 4.654 + } else { 4.655 + strcpy(buf, "."); 4.656 + } 4.657 + } 4.658 + return buf; 4.659 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/vector.cc Fri Aug 13 18:20:45 2010 +0100 5.3 @@ -0,0 +1,29 @@ 5.4 +#include "vector.h" 5.5 + 5.6 +Vector2::Vector2() : x(0), y(0) {} 5.7 + 5.8 +Vector2::Vector2(float x, float y) 5.9 +{ 5.10 + this->x = x; 5.11 + this->y = y; 5.12 +} 5.13 + 5.14 + 5.15 +Vector3::Vector3() : x(0), y(0), z(0) {} 5.16 + 5.17 +Vector3::Vector3(float x, float y, float z) 5.18 +{ 5.19 + this->x = x; 5.20 + this->y = y; 5.21 + this->z = z; 5.22 +} 5.23 + 5.24 +void Vector3::normalize() 5.25 +{ 5.26 + float len = sqrt(x * x + y * y + z * z); 5.27 + if(len != 0.0) { 5.28 + x /= len; 5.29 + y /= len; 5.30 + z /= len; 5.31 + } 5.32 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/vector.h Fri Aug 13 18:20:45 2010 +0100 6.3 @@ -0,0 +1,37 @@ 6.4 +#ifndef VECTOR_H_ 6.5 +#define VECTOR_H_ 6.6 + 6.7 +class Vector2 { 6.8 +public: 6.9 + float x, y; 6.10 + 6.11 + Vector2(); 6.12 + Vector2(float x, float y); 6.13 +}; 6.14 + 6.15 +class Vector3 { 6.16 +public: 6.17 + float x, y, z; 6.18 + 6.19 + Vector3(); 6.20 + Vector3(float x, float y, float z); 6.21 + 6.22 + void normalize(); 6.23 + inline float length(); 6.24 + inline float lengthsq(); 6.25 +}; 6.26 + 6.27 +inline Vector3 operator +(const Vector3 &a, const Vector3 &b); 6.28 +inline Vector3 operator -(const Vector3 &a, const Vector3 &b); 6.29 +inline Vector3 operator *(const Vector3 &a, const Vector3 &b); 6.30 +inline Vector3 operator /(const Vector3 &a, const Vector3 &b); 6.31 + 6.32 +inline Vector3 operator -(const Vector3 &vec); 6.33 +inline Vector3 operator *(const Vector3 &vec, float s); 6.34 + 6.35 +inline float dot(const Vector3 &a, const Vector3 &b); 6.36 +inline Vector3 cross(const Vector3 &a, const Vector3 &b); 6.37 + 6.38 +#include "vector.inl" 6.39 + 6.40 +#endif /* VECTOR_H_ */
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/vector.inl Fri Aug 13 18:20:45 2010 +0100 7.3 @@ -0,0 +1,53 @@ 7.4 +#include <math.h> 7.5 + 7.6 +inline float Vector3::length() 7.7 +{ 7.8 + return sqrt(x * x + y * y + z * z); 7.9 +} 7.10 + 7.11 +inline float Vector3::lengthsq() 7.12 +{ 7.13 + return x * x + y * y + z * z; 7.14 +} 7.15 + 7.16 +inline Vector3 operator +(const Vector3 &a, const Vector3 &b) 7.17 +{ 7.18 + return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); 7.19 +} 7.20 + 7.21 +inline Vector3 operator -(const Vector3 &a, const Vector3 &b) 7.22 +{ 7.23 + return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); 7.24 +} 7.25 + 7.26 +inline Vector3 operator *(const Vector3 &a, const Vector3 &b) 7.27 +{ 7.28 + return Vector3(a.x * b.x, a.y * b.y, a.z * b.z); 7.29 +} 7.30 + 7.31 +inline Vector3 operator /(const Vector3 &a, const Vector3 &b) 7.32 +{ 7.33 + return Vector3(a.x / b.x, a.y / b.y, a.z / b.z); 7.34 +} 7.35 + 7.36 + 7.37 +inline Vector3 operator -(const Vector3 &vec) 7.38 +{ 7.39 + return Vector3(-vec.x, -vec.y, -vec.z); 7.40 +} 7.41 + 7.42 +inline Vector3 operator *(const Vector3 &vec, float s) 7.43 +{ 7.44 + return Vector3(vec.x * s, vec.y * s, vec.z * s); 7.45 +} 7.46 + 7.47 + 7.48 +inline float dot(const Vector3 &a, const Vector3 &b) 7.49 +{ 7.50 + return a.x * b.x + a.y * b.y + a.z * b.z; 7.51 +} 7.52 + 7.53 +inline Vector3 cross(const Vector3 &a, const Vector3 &b) 7.54 +{ 7.55 + 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); 7.56 +}