clray
changeset 22:6c44e4b1726d
OMG alignment is a bitch
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 11 Aug 2010 04:30:35 +0100 |
parents | bd6c2b25f6e7 |
children | 51f115e337c2 |
files | rt.cl src/clray.cc src/mesh.cc src/mesh.h src/rt.cc src/rt.h src/scene.cc src/scene.h |
diffstat | 8 files changed, 848 insertions(+), 833 deletions(-) [+] |
line diff
1.1 --- a/rt.cl Tue Aug 10 07:24:18 2010 +0100 1.2 +++ b/rt.cl Wed Aug 11 04:30:35 2010 +0100 1.3 @@ -1,10 +1,10 @@ 1.4 /* vim: set ft=opencl:ts=4:sw=4 */ 1.5 1.6 struct RendInfo { 1.7 + float4 ambient; 1.8 int xsz, ysz; 1.9 int num_faces, num_lights; 1.10 int max_iter; 1.11 - float4 ambient; 1.12 }; 1.13 1.14 struct Vertex { 1.15 @@ -88,7 +88,7 @@ 1.16 transform_ray(&ray, xform, invtrans); 1.17 1.18 float4 pixel = (float4)(0, 0, 0, 0); 1.19 - float4 energy = (float4)(1.0, 1.0, 1.0, 1.0); 1.20 + float4 energy = (float4)(1.0, 1.0, 1.0, 0.0); 1.21 int iter = 0; 1.22 1.23 while(iter++ < rinf->max_iter && mean(energy) > MIN_ENERGY) { 1.24 @@ -136,10 +136,10 @@ 1.25 float4 vref = reflect(vdir, norm); 1.26 1.27 float diff = fmax(dot(ldir, norm), 0.0f); 1.28 - dcol += sp->mat.kd * diff * scn->lights[i].color; 1.29 + dcol += sp->mat.kd * scn->lights[i].color * diff; 1.30 1.31 float spec = powr(fmax(dot(ldir, vref), 0.0f), sp->mat.spow); 1.32 - scol += sp->mat.ks * spec * scn->lights[i].color; 1.33 + scol += sp->mat.ks * scn->lights[i].color * spec; 1.34 } 1.35 } 1.36
2.1 --- a/src/clray.cc Tue Aug 10 07:24:18 2010 +0100 2.2 +++ b/src/clray.cc Wed Aug 11 04:30:35 2010 +0100 2.3 @@ -9,7 +9,7 @@ 2.4 #endif 2.5 #include "rt.h" 2.6 #include "matrix.h" 2.7 -#include "mesh.h" 2.8 +#include "scene.h" 2.9 2.10 void cleanup(); 2.11 void disp(); 2.12 @@ -25,7 +25,7 @@ 2.13 static float cam_theta, cam_phi = 25.0; 2.14 static float cam_dist = 10.0; 2.15 2.16 -static bool dbg_glrender = true; 2.17 +static bool dbg_glrender = false; 2.18 2.19 static Scene scn; 2.20 2.21 @@ -128,6 +128,7 @@ 2.22 dbg_render_gl(&scn); 2.23 } else { 2.24 glEnable(GL_TEXTURE_2D); 2.25 + glDisable(GL_LIGHTING); 2.26 2.27 glBegin(GL_QUADS); 2.28 glColor3f(1, 1, 1);
3.1 --- a/src/mesh.cc Tue Aug 10 07:24:18 2010 +0100 3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 3.3 @@ -1,755 +0,0 @@ 3.4 -#include <stdio.h> 3.5 -#include <stdlib.h> 3.6 -#include <string.h> 3.7 -#include <math.h> 3.8 -#include <errno.h> 3.9 -#include <limits.h> 3.10 -#include <string> 3.11 -#include <vector> 3.12 -#include <map> 3.13 -#include "mesh.h" 3.14 - 3.15 -#ifndef PATH_MAX 3.16 -#define PATH_MAX 512 3.17 -#endif 3.18 - 3.19 -using namespace std; 3.20 - 3.21 -#define COMMANDS \ 3.22 - CMD(V), \ 3.23 - CMD(VN), \ 3.24 - CMD(VT), \ 3.25 - CMD(F), \ 3.26 - CMD(O), \ 3.27 - CMD(G), \ 3.28 - CMD(MTLLIB), \ 3.29 - CMD(USEMTL), \ 3.30 - CMD(NEWMTL), \ 3.31 - CMD(KA), \ 3.32 - CMD(KD), \ 3.33 - CMD(KS), \ 3.34 - CMD(KR), \ 3.35 - CMD(NS), \ 3.36 - CMD(NI), \ 3.37 - CMD(D), \ 3.38 - CMD(TR), \ 3.39 - CMD(MAP_KD), \ 3.40 - CMD(MAP_KS), \ 3.41 - CMD(MAP_NS), \ 3.42 - CMD(MAP_D), \ 3.43 - CMD(REFL), \ 3.44 - CMD(BUMP) 3.45 - 3.46 -#define CMD(x) CMD_##x 3.47 -enum { 3.48 - COMMANDS, 3.49 - CMD_UNK 3.50 -}; 3.51 -#undef CMD 3.52 - 3.53 -#define CMD(x) #x 3.54 -static const char *cmd_names[] = { 3.55 - COMMANDS, 3.56 - 0 3.57 -}; 3.58 -#undef CMD 3.59 - 3.60 -struct Vector3 { 3.61 - float x, y, z; 3.62 - 3.63 - Vector3() { x = y = z = 0.0; } 3.64 - Vector3(float a, float b, float c) { x = a; y = b; z = c; } 3.65 - 3.66 - void normalize() { float len = sqrt(x * x + y * y + z * z); x /= len; y /= len; z /= len; } 3.67 -}; 3.68 - 3.69 -struct Vector2 { 3.70 - float x, y; 3.71 - 3.72 - Vector2() { x = y = 0.0; } 3.73 - Vector2(float a, float b) { x = a; y = b; } 3.74 -}; 3.75 - 3.76 -struct obj_face { 3.77 - int elem; 3.78 - int v[4], n[4], t[4]; 3.79 -}; 3.80 - 3.81 -struct obj_file { 3.82 - string cur_obj, cur_mat; 3.83 - vector<Vector3> v, vn, vt; 3.84 - vector<obj_face> f; 3.85 -}; 3.86 - 3.87 -struct obj_mat { 3.88 - string name; // newmtl <name> 3.89 - Vector3 ambient, diffuse, specular; // Ka, Kd, Ks 3.90 - float shininess; // Ns 3.91 - float ior; // Ni 3.92 - float alpha; // d, Tr 3.93 - float refl; // Kr (my extesnsion) 3.94 - 3.95 - string tex_dif, tex_spec, tex_shin, tex_alpha; // map_Kd, map_Ks, map_Ns, map_d 3.96 - string tex_refl; // refl -type sphere|cube file 3.97 - string tex_bump; // bump 3.98 - 3.99 - obj_mat() { reset(); } 3.100 - 3.101 - void reset() { 3.102 - ambient = diffuse = Vector3(0.5, 0.5, 0.5); 3.103 - specular = Vector3(0.0, 0.0, 0.0); 3.104 - name = tex_dif = tex_spec = tex_shin = tex_alpha = tex_refl = tex_bump = ""; 3.105 - shininess = 0; 3.106 - ior = alpha = 1; 3.107 - refl = 0.0; 3.108 - } 3.109 -}; 3.110 - 3.111 -static bool read_materials(FILE *fp, vector<obj_mat> *vmtl); 3.112 -static Mesh *cons_mesh(obj_file *obj); 3.113 - 3.114 -static int get_cmd(char *str); 3.115 -static bool is_int(const char *str); 3.116 -static bool is_float(const char *str); 3.117 -static bool parse_vec(Vector3 *vec); 3.118 -static bool parse_color(Vector3 *col); 3.119 -static bool parse_face(obj_face *face); 3.120 -static const char *parse_map(); 3.121 - 3.122 -static bool find_file(char *res, int sz, const char *fname, const char *path = ".", const char *mode = "rb"); 3.123 -static const char *dirname(const char *str); 3.124 - 3.125 -static Vector3 operator -(const Vector3 &a, const Vector3 &b); 3.126 -static Vector3 cross(const Vector3 &a, const Vector3 &b); 3.127 - 3.128 -static map<string, int> matnames; 3.129 - 3.130 - 3.131 -#define FEQ(a, b) (fabs((a) - (b)) < 1e-8) 3.132 -bool Face::operator ==(const Face &f) const 3.133 -{ 3.134 - for(int i=0; i<3; i++) { 3.135 - for(int j=0; j<3; j++) { 3.136 - if(!FEQ(v[i].pos[j], f.v[i].pos[j])) { 3.137 - return false; 3.138 - } 3.139 - if(!FEQ(v[i].normal[j], f.v[i].normal[j])) { 3.140 - return false; 3.141 - } 3.142 - } 3.143 - if(!FEQ(normal[i], f.normal[i])) { 3.144 - return false; 3.145 - } 3.146 - } 3.147 - return true; 3.148 -} 3.149 - 3.150 -bool Scene::add_mesh(Mesh *m) 3.151 -{ 3.152 - // make sure triangles have material ids 3.153 - for(size_t i=0; i<m->faces.size(); i++) { 3.154 - m->faces[i].matid = m->matid; 3.155 - } 3.156 - meshes.push_back(m); 3.157 - return true; 3.158 -} 3.159 - 3.160 -int Scene::get_num_meshes() const 3.161 -{ 3.162 - return (int)meshes.size(); 3.163 -} 3.164 - 3.165 -int Scene::get_num_faces() const 3.166 -{ 3.167 - int num_faces = 0; 3.168 - for(size_t i=0; i<meshes.size(); i++) { 3.169 - num_faces += meshes[i]->faces.size(); 3.170 - } 3.171 - return num_faces; 3.172 -} 3.173 - 3.174 -int Scene::get_num_materials() const 3.175 -{ 3.176 - return (int)matlib.size(); 3.177 -} 3.178 - 3.179 -Material *Scene::get_materials() 3.180 -{ 3.181 - if(matlib.empty()) { 3.182 - return 0; 3.183 - } 3.184 - return &matlib[0]; 3.185 -} 3.186 - 3.187 -const Material *Scene::get_materials() const 3.188 -{ 3.189 - if(matlib.empty()) { 3.190 - return 0; 3.191 - } 3.192 - return &matlib[0]; 3.193 -} 3.194 - 3.195 - 3.196 -#define INVALID_IDX INT_MIN 3.197 - 3.198 -#define SEP " \t\n\r\v" 3.199 -#define BUF_SZ 512 3.200 - 3.201 -bool Scene::load(const char *fname) 3.202 -{ 3.203 - FILE *fp; 3.204 - 3.205 - if(!(fp = fopen(fname, "rb"))) { 3.206 - fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno)); 3.207 - return false; 3.208 - } 3.209 - 3.210 - bool res = load(fp); 3.211 - fclose(fp); 3.212 - return res; 3.213 -} 3.214 - 3.215 -bool Scene::load(FILE *fp) 3.216 -{ 3.217 - static int seq; 3.218 - char cur_name[16]; 3.219 - 3.220 - obj_file obj; 3.221 - 3.222 - sprintf(cur_name, "default%02d.obj", seq++); 3.223 - obj.cur_obj = cur_name; 3.224 - 3.225 - int prev_cmd = 0, obj_added = 0; 3.226 - for(;;) { 3.227 - Vector3 vec; 3.228 - obj_face face; 3.229 - 3.230 - char line[BUF_SZ]; 3.231 - fgets(line, sizeof line, fp); 3.232 - if(feof(fp)) { 3.233 - break; 3.234 - } 3.235 - 3.236 - char *tok; 3.237 - if(!(tok = strtok(line, SEP))) { 3.238 - continue; // ignore empty lines 3.239 - } 3.240 - 3.241 - int cmd; 3.242 - if((cmd = get_cmd(tok)) == -1) { 3.243 - continue; // ignore unknown commands ... 3.244 - } 3.245 - 3.246 - switch(cmd) { 3.247 - case CMD_V: 3.248 - if(!parse_vec(&vec)) { 3.249 - continue; 3.250 - } 3.251 - obj.v.push_back(vec); 3.252 - break; 3.253 - 3.254 - case CMD_VN: 3.255 - if(!parse_vec(&vec)) { 3.256 - continue; 3.257 - } 3.258 - obj.vn.push_back(vec); 3.259 - break; 3.260 - 3.261 - case CMD_VT: 3.262 - if(!parse_vec(&vec)) { 3.263 - continue; 3.264 - } 3.265 - vec.y = 1.0 - vec.y; 3.266 - obj.vt.push_back(vec); 3.267 - break; 3.268 - 3.269 - case CMD_O: 3.270 - case CMD_G: 3.271 - if(prev_cmd == CMD_O || prev_cmd == CMD_G) { 3.272 - break; // just in case we've got both of them in a row 3.273 - } 3.274 - /* if we have any previous data, group them up, add the object 3.275 - * and continue with the new one... 3.276 - */ 3.277 - if(!obj.f.empty()) { 3.278 - Mesh *mesh = cons_mesh(&obj); 3.279 - mesh->matid = matnames[obj.cur_mat]; 3.280 - add_mesh(mesh); 3.281 - obj_added++; 3.282 - 3.283 - obj.f.clear(); // clean the face list 3.284 - } 3.285 - if((tok = strtok(0, SEP))) { 3.286 - obj.cur_obj = tok; 3.287 - } else { 3.288 - sprintf(cur_name, "default%02d.obj", seq++); 3.289 - obj.cur_obj = cur_name; 3.290 - } 3.291 - break; 3.292 - 3.293 - case CMD_MTLLIB: 3.294 - if((tok = strtok(0, SEP))) { 3.295 - char path[PATH_MAX]; 3.296 - 3.297 - sprintf(path, ".:%s", dirname(tok)); 3.298 - if(!find_file(path, PATH_MAX, tok, path)) { 3.299 - fprintf(stderr, "material library not found: %s\n", tok); 3.300 - continue; 3.301 - } 3.302 - 3.303 - FILE *mfile; 3.304 - if(!(mfile = fopen(path, "rb"))) { 3.305 - fprintf(stderr, "failed to open material library: %s\n", path); 3.306 - continue; 3.307 - } 3.308 - 3.309 - // load all materials of the mtl file into a vector 3.310 - vector<obj_mat> vmtl; 3.311 - if(!read_materials(mfile, &vmtl)) { 3.312 - continue; 3.313 - } 3.314 - fclose(mfile); 3.315 - 3.316 - // and add them all to the scene 3.317 - for(size_t i=0; i<vmtl.size(); i++) { 3.318 - Material mat; 3.319 - 3.320 - mat.kd[0] = vmtl[i].diffuse.x; 3.321 - mat.kd[1] = vmtl[i].diffuse.y; 3.322 - mat.kd[2] = vmtl[i].diffuse.z; 3.323 - 3.324 - mat.ks[0] = vmtl[i].specular.x; 3.325 - mat.ks[1] = vmtl[i].specular.y; 3.326 - mat.ks[2] = vmtl[i].specular.z; 3.327 - 3.328 - mat.kt = 1.0 - vmtl[i].alpha; 3.329 - mat.kr = vmtl[i].refl; 3.330 - mat.spow = vmtl[i].shininess; 3.331 - 3.332 - matlib.push_back(mat); 3.333 - matnames[vmtl[i].name] = i; 3.334 - } 3.335 - } 3.336 - break; 3.337 - 3.338 - case CMD_USEMTL: 3.339 - if((tok = strtok(0, SEP))) { 3.340 - obj.cur_mat = tok; 3.341 - } else { 3.342 - obj.cur_mat = ""; 3.343 - } 3.344 - break; 3.345 - 3.346 - case CMD_F: 3.347 - if(!parse_face(&face)) { 3.348 - continue; 3.349 - } 3.350 - 3.351 - // convert negative indices to regular indices 3.352 - for(int i=0; i<4; i++) { 3.353 - if(face.v[i] < 0 && face.v[i] != INVALID_IDX) { 3.354 - face.v[i] = obj.v.size() + face.v[i]; 3.355 - } 3.356 - if(face.n[i] < 0 && face.n[i] != INVALID_IDX) { 3.357 - face.n[i] = obj.vn.size() + face.n[i]; 3.358 - } 3.359 - if(face.t[i] < 0 && face.t[i] != INVALID_IDX) { 3.360 - face.t[i] = obj.vt.size() + face.t[i]; 3.361 - } 3.362 - } 3.363 - 3.364 - // break quads into triangles if needed 3.365 - obj.f.push_back(face); 3.366 - if(face.elem == 4) { 3.367 - face.v[1] = face.v[2]; 3.368 - face.n[1] = face.n[2]; 3.369 - face.t[1] = face.t[2]; 3.370 - 3.371 - face.v[2] = face.v[3]; 3.372 - face.n[2] = face.n[3]; 3.373 - face.t[2] = face.t[3]; 3.374 - 3.375 - obj.f.push_back(face); 3.376 - } 3.377 - break; 3.378 - 3.379 - default: 3.380 - break; // ignore unknown commands 3.381 - } 3.382 - 3.383 - prev_cmd = cmd; 3.384 - } 3.385 - 3.386 - // reached end of file... 3.387 - if(!obj.f.empty()) { 3.388 - Mesh *mesh = cons_mesh(&obj); 3.389 - mesh->matid = matnames[obj.cur_mat]; 3.390 - add_mesh(mesh); 3.391 - obj_added++; 3.392 - } 3.393 - 3.394 - return obj_added > 0; 3.395 -} 3.396 - 3.397 -static Mesh *cons_mesh(obj_file *obj) 3.398 -{ 3.399 - Mesh *mesh; 3.400 - 3.401 - // need at least one of each element 3.402 - bool added_norm = false, added_tc = false; 3.403 - if(obj->vn.empty()) { 3.404 - obj->vn.push_back(Vector3(0, 0, 0)); 3.405 - added_norm = true; 3.406 - } 3.407 - if(obj->vt.empty()) { 3.408 - obj->vt.push_back(Vector3(0, 0, 0)); 3.409 - added_tc = true; 3.410 - } 3.411 - 3.412 - mesh = new Mesh; 3.413 - 3.414 - for(size_t i=0; i<obj->f.size(); i++) { 3.415 - Face face; 3.416 - Vector3 v[3]; 3.417 - 3.418 - for(int j=0; j<3; j++) { 3.419 - obj_face *f = &obj->f[i]; 3.420 - 3.421 - face.v[j].pos[0] = v[j].x = obj->v[f->v[j]].x; 3.422 - face.v[j].pos[1] = v[j].y = obj->v[f->v[j]].y; 3.423 - face.v[j].pos[2] = v[j].z = obj->v[f->v[j]].z; 3.424 - face.v[j].pos[3] = 0.0; 3.425 - 3.426 - int nidx = f->n[j] < 0 ? 0 : f->n[j]; 3.427 - face.v[j].normal[0] = obj->vn[nidx].x; 3.428 - face.v[j].normal[1] = obj->vn[nidx].y; 3.429 - face.v[j].normal[2] = obj->vn[nidx].z; 3.430 - face.v[j].normal[3] = 0.0; 3.431 - 3.432 - int tidx = f->t[j] < 0 ? 0 : f->t[j]; 3.433 - face.v[j].tex[0] = obj->vt[tidx].x; 3.434 - face.v[j].tex[1] = obj->vt[tidx].y; 3.435 - } 3.436 - 3.437 - Vector3 a = v[1] - v[0]; 3.438 - Vector3 b = v[2] - v[0]; 3.439 - Vector3 n = cross(a, b); 3.440 - n.normalize(); 3.441 - 3.442 - face.normal[0] = n.x; 3.443 - face.normal[1] = n.y; 3.444 - face.normal[2] = n.z; 3.445 - face.normal[3] = 0.0; 3.446 - 3.447 - mesh->faces.push_back(face); 3.448 - } 3.449 - 3.450 - if(added_norm) { 3.451 - obj->vn.pop_back(); 3.452 - } 3.453 - if(added_tc) { 3.454 - obj->vt.pop_back(); 3.455 - } 3.456 - 3.457 - return mesh; 3.458 -} 3.459 - 3.460 -static bool read_materials(FILE *fp, vector<obj_mat> *vmtl) 3.461 -{ 3.462 - obj_mat mat; 3.463 - 3.464 - for(;;) { 3.465 - char line[BUF_SZ]; 3.466 - fgets(line, sizeof line, fp); 3.467 - if(feof(fp)) { 3.468 - break; 3.469 - } 3.470 - 3.471 - char *tok; 3.472 - if(!(tok = strtok(line, SEP))) { 3.473 - continue; 3.474 - } 3.475 - 3.476 - int cmd; 3.477 - if((cmd = get_cmd(tok)) == -1) { 3.478 - continue; 3.479 - } 3.480 - 3.481 - switch(cmd) { 3.482 - case CMD_NEWMTL: 3.483 - // add the previous material, and start a new one 3.484 - if(mat.name.length() > 0) { 3.485 - printf("Adding material: %s\n", mat.name.c_str()); 3.486 - vmtl->push_back(mat); 3.487 - mat.reset(); 3.488 - } 3.489 - if((tok = strtok(0, SEP))) { 3.490 - mat.name = tok; 3.491 - } 3.492 - break; 3.493 - 3.494 - case CMD_KA: 3.495 - parse_color(&mat.ambient); 3.496 - break; 3.497 - 3.498 - case CMD_KD: 3.499 - parse_color(&mat.diffuse); 3.500 - break; 3.501 - 3.502 - case CMD_KS: 3.503 - parse_color(&mat.specular); 3.504 - break; 3.505 - 3.506 - case CMD_KR: 3.507 - if((tok = strtok(0, SEP)) && is_float(tok)) { 3.508 - mat.refl = atof(tok); 3.509 - } 3.510 - break; 3.511 - 3.512 - case CMD_NS: 3.513 - if((tok = strtok(0, SEP)) && is_float(tok)) { 3.514 - mat.shininess = atof(tok); 3.515 - } 3.516 - break; 3.517 - 3.518 - case CMD_NI: 3.519 - if((tok = strtok(0, SEP)) && is_float(tok)) { 3.520 - mat.ior = atof(tok); 3.521 - } 3.522 - break; 3.523 - 3.524 - case CMD_D: 3.525 - case CMD_TR: 3.526 - { 3.527 - Vector3 c; 3.528 - if(parse_color(&c)) { 3.529 - mat.alpha = cmd == CMD_D ? c.x : 1.0 - c.x; 3.530 - } 3.531 - } 3.532 - break; 3.533 - 3.534 - case CMD_MAP_KD: 3.535 - mat.tex_dif = parse_map(); 3.536 - break; 3.537 - 3.538 - default: 3.539 - break; 3.540 - } 3.541 - } 3.542 - 3.543 - if(mat.name.length() > 0) { 3.544 - printf("Adding material: %s\n", mat.name.c_str()); 3.545 - vmtl->push_back(mat); 3.546 - } 3.547 - return true; 3.548 -} 3.549 - 3.550 -static int get_cmd(char *str) 3.551 -{ 3.552 - char *s = str; 3.553 - while((*s = toupper(*s))) s++; 3.554 - 3.555 - for(int i=0; cmd_names[i]; i++) { 3.556 - if(strcmp(str, cmd_names[i]) == 0) { 3.557 - return i; 3.558 - } 3.559 - } 3.560 - return CMD_UNK; 3.561 -} 3.562 - 3.563 -static bool is_int(const char *str) 3.564 -{ 3.565 - char *tmp; 3.566 - strtol(str, &tmp, 10); 3.567 - return tmp != str; 3.568 -} 3.569 - 3.570 -static bool is_float(const char *str) 3.571 -{ 3.572 - char *tmp; 3.573 - strtod(str, &tmp); 3.574 - return tmp != str; 3.575 -} 3.576 - 3.577 -static bool parse_vec(Vector3 *vec) 3.578 -{ 3.579 - for(int i=0; i<3; i++) { 3.580 - char *tok; 3.581 - 3.582 - if(!(tok = strtok(0, SEP)) || !is_float(tok)) { 3.583 - if(i < 2) { 3.584 - return false; 3.585 - } 3.586 - vec->z = 0.0; 3.587 - } else { 3.588 - float v = atof(tok); 3.589 - 3.590 - switch(i) { 3.591 - case 0: 3.592 - vec->x = v; 3.593 - break; 3.594 - case 1: 3.595 - vec->y = v; 3.596 - break; 3.597 - case 2: 3.598 - vec->z = v; 3.599 - break; 3.600 - } 3.601 - } 3.602 - } 3.603 - return true; 3.604 -} 3.605 - 3.606 -static bool parse_color(Vector3 *col) 3.607 -{ 3.608 - for(int i=0; i<3; i++) { 3.609 - char *tok; 3.610 - 3.611 - if(!(tok = strtok(0, SEP)) || !is_float(tok)) { 3.612 - col->y = col->z = col->x; 3.613 - return i > 0 ? true : false; 3.614 - } 3.615 - 3.616 - float v = atof(tok); 3.617 - switch(i) { 3.618 - case 0: 3.619 - col->x = v; 3.620 - break; 3.621 - case 1: 3.622 - col->y = v; 3.623 - break; 3.624 - case 2: 3.625 - col->z = v; 3.626 - break; 3.627 - } 3.628 - } 3.629 - return true; 3.630 -} 3.631 - 3.632 -static bool parse_face(obj_face *face) 3.633 -{ 3.634 - char *tok[] = {0, 0, 0, 0}; 3.635 - face->elem = 0; 3.636 - 3.637 - for(int i=0; i<4; i++) { 3.638 - if((!(tok[i] = strtok(0, SEP)) || !is_int(tok[i]))) { 3.639 - if(i < 3) return false; // less than 3 verts? not a polygon 3.640 - } else { 3.641 - face->elem++; 3.642 - } 3.643 - } 3.644 - 3.645 - for(int i=0; i<4; i++) { 3.646 - char *subtok = tok[i]; 3.647 - 3.648 - if(!subtok || !*subtok || !is_int(subtok)) { 3.649 - if(i < 3) { 3.650 - return false; 3.651 - } 3.652 - face->v[i] = INVALID_IDX; 3.653 - } else { 3.654 - face->v[i] = atoi(subtok); 3.655 - if(face->v[i] > 0) face->v[i]--; /* convert to 0-based */ 3.656 - } 3.657 - 3.658 - while(subtok && *subtok && *subtok != '/') { 3.659 - subtok++; 3.660 - } 3.661 - if(subtok && *subtok && *++subtok && is_int(subtok)) { 3.662 - face->t[i] = atoi(subtok); 3.663 - if(face->t[i] > 0) face->t[i]--; /* convert to 0-based */ 3.664 - } else { 3.665 - face->t[i] = INVALID_IDX; 3.666 - } 3.667 - 3.668 - while(subtok && *subtok && *subtok != '/') { 3.669 - subtok++; 3.670 - } 3.671 - if(subtok && *subtok && *++subtok && is_int(subtok)) { 3.672 - face->n[i] = atoi(subtok); 3.673 - if(face->n[i] > 0) face->n[i]--; /* convert to 0-based */ 3.674 - } else { 3.675 - face->n[i] = INVALID_IDX; 3.676 - } 3.677 - } 3.678 - 3.679 - return true; 3.680 -} 3.681 - 3.682 -static const char *parse_map() 3.683 -{ 3.684 - char *tok, *prev = 0; 3.685 - 3.686 - while((tok = strtok(0, SEP))) { 3.687 - prev = tok; 3.688 - } 3.689 - 3.690 - return prev ? prev : ""; 3.691 -} 3.692 - 3.693 -static bool find_file(char *res, int sz, const char *fname, const char *path, const char *mode) 3.694 -{ 3.695 - FILE *fp; 3.696 - const char *beg, *end; 3.697 - int fnamelen = strlen(fname); 3.698 - 3.699 - beg = path; 3.700 - while(beg && *beg) { 3.701 - end = beg; 3.702 - while(*end && *end != ':') { 3.703 - end++; 3.704 - } 3.705 - 3.706 - int res_len = end - beg; 3.707 - char *pathname = (char*)alloca(res_len + fnamelen + 2); 3.708 - memcpy(pathname, beg, res_len); 3.709 - pathname[res_len] = 0; 3.710 - if(res_len) { 3.711 - strcat(pathname, "/"); 3.712 - } 3.713 - strcat(pathname, fname); 3.714 - 3.715 - if((fp = fopen(pathname, mode))) { 3.716 - fclose(fp); 3.717 - strncpy(res, pathname, sz); 3.718 - return true; 3.719 - } 3.720 - 3.721 - beg += res_len; 3.722 - if(*beg == ':') beg++; 3.723 - } 3.724 - return false; 3.725 -} 3.726 - 3.727 -static const char *dirname(const char *str) 3.728 -{ 3.729 - static char buf[PATH_MAX]; 3.730 - 3.731 - if(!str || !*str) { 3.732 - strcpy(buf, "."); 3.733 - } else { 3.734 - strncpy(buf, str, PATH_MAX); 3.735 - char *ptr = strrchr(buf, '/'); 3.736 - 3.737 - if(ptr && *ptr) { 3.738 - *ptr = 0; 3.739 - } else { 3.740 - strcpy(buf, "."); 3.741 - } 3.742 - } 3.743 - return buf; 3.744 -} 3.745 - 3.746 -static Vector3 operator -(const Vector3 &a, const Vector3 &b) 3.747 -{ 3.748 - return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); 3.749 -} 3.750 - 3.751 -static Vector3 cross(const Vector3 &a, const Vector3 &b) 3.752 -{ 3.753 - Vector3 res; 3.754 - res.x = a.y * b.z - a.z * b.y; 3.755 - res.y = a.z * b.x - a.x * b.z; 3.756 - res.z = a.x * b.y - a.y * b.x; 3.757 - return res; 3.758 -}
4.1 --- a/src/mesh.h Tue Aug 10 07:24:18 2010 +0100 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,51 +0,0 @@ 4.4 -#ifndef MESH_H_ 4.5 -#define MESH_H_ 4.6 - 4.7 -#include <vector> 4.8 - 4.9 -struct Vertex { 4.10 - float pos[4]; 4.11 - float normal[4]; 4.12 - float tex[4]; 4.13 - float padding[4]; 4.14 -}; 4.15 - 4.16 -struct Face { 4.17 - Vertex v[3]; 4.18 - float normal[4]; 4.19 - int matid; 4.20 - int padding[3]; 4.21 - 4.22 - bool operator ==(const Face &f) const; 4.23 -}; 4.24 - 4.25 -struct Material { 4.26 - float kd[4], ks[4]; 4.27 - float kr, kt; 4.28 - float spow; 4.29 - float padding; 4.30 -}; 4.31 - 4.32 -struct Mesh { 4.33 - std::vector<Face> faces; 4.34 - int matid; 4.35 -}; 4.36 - 4.37 -class Scene { 4.38 -public: 4.39 - std::vector<Mesh*> meshes; 4.40 - std::vector<Material> matlib; 4.41 - 4.42 - bool add_mesh(Mesh *m); 4.43 - int get_num_meshes() const; 4.44 - int get_num_materials() const; 4.45 - int get_num_faces() const; 4.46 - 4.47 - Material *get_materials(); 4.48 - const Material *get_materials() const; 4.49 - 4.50 - bool load(const char *fname); 4.51 - bool load(FILE *fp); 4.52 -}; 4.53 - 4.54 -#endif /* MESH_H_ */
5.1 --- a/src/rt.cc Tue Aug 10 07:24:18 2010 +0100 5.2 +++ b/src/rt.cc Wed Aug 11 04:30:35 2010 +0100 5.3 @@ -4,7 +4,7 @@ 5.4 #include <assert.h> 5.5 #include "ogl.h" 5.6 #include "ocl.h" 5.7 -#include "mesh.h" 5.8 +#include "scene.h" 5.9 5.10 // kernel arguments 5.11 enum { 5.12 @@ -21,10 +21,10 @@ 5.13 }; 5.14 5.15 struct RendInfo { 5.16 + float ambient[4]; 5.17 int xsz, ysz; 5.18 int num_faces, num_lights; 5.19 int max_iter; 5.20 - float ambient[4]; 5.21 }; 5.22 5.23 struct Ray { 5.24 @@ -44,7 +44,7 @@ 5.25 static int global_size; 5.26 5.27 static Light lightlist[] = { 5.28 - {{-8, 15, -18, 0}, {1, 1, 1, 1}} 5.29 + {{-8, 15, 18, 0}, {1, 1, 1, 1}} 5.30 }; 5.31 5.32 5.33 @@ -54,7 +54,7 @@ 5.34 bool init_renderer(int xsz, int ysz, Scene *scn) 5.35 { 5.36 // render info 5.37 - rinf.ambient[0] = rinf.ambient[1] = rinf.ambient[2] = 0.075; 5.38 + rinf.ambient[0] = rinf.ambient[1] = rinf.ambient[2] = 0.0; 5.39 rinf.ambient[3] = 0.0; 5.40 5.41 rinf.xsz = xsz; 5.42 @@ -115,13 +115,9 @@ 5.43 5.44 bool render() 5.45 { 5.46 - printf("Running kernel... "); 5.47 - fflush(stdout); 5.48 if(!prog->run(1, global_size)) { 5.49 return false; 5.50 } 5.51 - printf("done\n"); 5.52 - 5.53 5.54 CLMemBuffer *mbuf = prog->get_arg_buffer(KARG_FRAMEBUFFER); 5.55 void *fb = map_mem_buffer(mbuf, MAP_RD); 5.56 @@ -130,6 +126,12 @@ 5.57 return false; 5.58 } 5.59 5.60 + static int foo = 0; 5.61 + if(!foo++) { 5.62 + bool write_ppm(const char *fname, float *fb, int xsz, int ysz); 5.63 + write_ppm("foo.ppm", (float*)fb, rinf.xsz, rinf.ysz); 5.64 + } 5.65 + 5.66 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rinf.xsz, rinf.ysz, GL_RGBA, GL_FLOAT, fb); 5.67 unmap_mem_buffer(mbuf); 5.68 return true; 5.69 @@ -148,7 +150,7 @@ 5.70 5.71 void dbg_render_gl(Scene *scn) 5.72 { 5.73 - glPushAttrib(GL_ENABLE_BIT | GL_TRANSFORM_BIT); 5.74 + glPushAttrib(GL_ENABLE_BIT | GL_TRANSFORM_BIT | GL_LIGHTING_BIT); 5.75 5.76 for(int i=0; i<rinf.num_lights; i++) { 5.77 float lpos[4]; 5.78 @@ -158,12 +160,12 @@ 5.79 5.80 glLightfv(GL_LIGHT0 + i, GL_POSITION, lpos); 5.81 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, lightlist[i].color); 5.82 + glEnable(GL_LIGHT0 + i); 5.83 } 5.84 5.85 glDisable(GL_TEXTURE_2D); 5.86 glEnable(GL_DEPTH_TEST); 5.87 glEnable(GL_LIGHTING); 5.88 - glEnable(GL_LIGHT0); 5.89 5.90 glMatrixMode(GL_PROJECTION); 5.91 glPushMatrix(); 5.92 @@ -194,6 +196,8 @@ 5.93 5.94 glPopMatrix(); 5.95 glPopAttrib(); 5.96 + 5.97 + assert(glGetError() == GL_NO_ERROR); 5.98 } 5.99 5.100 void set_xform(float *matrix, float *invtrans) 5.101 @@ -204,20 +208,10 @@ 5.102 5.103 float *mem = (float*)map_mem_buffer(mbuf_xform, MAP_WR); 5.104 memcpy(mem, matrix, 16 * sizeof *mem); 5.105 - /*printf("-- xform:\n"); 5.106 - for(int i=0; i<16; i++) { 5.107 - printf("%2.3f\t", mem[i]); 5.108 - if(i % 4 == 3) putchar('\n'); 5.109 - }*/ 5.110 unmap_mem_buffer(mbuf_xform); 5.111 5.112 mem = (float*)map_mem_buffer(mbuf_invtrans, MAP_WR); 5.113 memcpy(mem, invtrans, 16 * sizeof *mem); 5.114 - /*printf("-- inverse-transpose:\n"); 5.115 - for(int i=0; i<16; i++) { 5.116 - printf("%2.3f\t", mem[i]); 5.117 - if(i % 4 == 3) putchar('\n'); 5.118 - }*/ 5.119 unmap_mem_buffer(mbuf_invtrans); 5.120 } 5.121
6.1 --- a/src/rt.h Tue Aug 10 07:24:18 2010 +0100 6.2 +++ b/src/rt.h Wed Aug 11 04:30:35 2010 +0100 6.3 @@ -1,7 +1,7 @@ 6.4 #ifndef RT_H_ 6.5 #define RT_H_ 6.6 6.7 -#include "mesh.h" 6.8 +#include "scene.h" 6.9 6.10 bool init_renderer(int xsz, int ysz, Scene *scn); 6.11 void destroy_renderer();
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/scene.cc Wed Aug 11 04:30:35 2010 +0100 7.3 @@ -0,0 +1,755 @@ 7.4 +#include <stdio.h> 7.5 +#include <stdlib.h> 7.6 +#include <string.h> 7.7 +#include <math.h> 7.8 +#include <errno.h> 7.9 +#include <limits.h> 7.10 +#include <string> 7.11 +#include <vector> 7.12 +#include <map> 7.13 +#include "scene.h" 7.14 + 7.15 +#ifndef PATH_MAX 7.16 +#define PATH_MAX 512 7.17 +#endif 7.18 + 7.19 +using namespace std; 7.20 + 7.21 +#define COMMANDS \ 7.22 + CMD(V), \ 7.23 + CMD(VN), \ 7.24 + CMD(VT), \ 7.25 + CMD(F), \ 7.26 + CMD(O), \ 7.27 + CMD(G), \ 7.28 + CMD(MTLLIB), \ 7.29 + CMD(USEMTL), \ 7.30 + CMD(NEWMTL), \ 7.31 + CMD(KA), \ 7.32 + CMD(KD), \ 7.33 + CMD(KS), \ 7.34 + CMD(KR), \ 7.35 + CMD(NS), \ 7.36 + CMD(NI), \ 7.37 + CMD(D), \ 7.38 + CMD(TR), \ 7.39 + CMD(MAP_KD), \ 7.40 + CMD(MAP_KS), \ 7.41 + CMD(MAP_NS), \ 7.42 + CMD(MAP_D), \ 7.43 + CMD(REFL), \ 7.44 + CMD(BUMP) 7.45 + 7.46 +#define CMD(x) CMD_##x 7.47 +enum { 7.48 + COMMANDS, 7.49 + CMD_UNK 7.50 +}; 7.51 +#undef CMD 7.52 + 7.53 +#define CMD(x) #x 7.54 +static const char *cmd_names[] = { 7.55 + COMMANDS, 7.56 + 0 7.57 +}; 7.58 +#undef CMD 7.59 + 7.60 +struct Vector3 { 7.61 + float x, y, z; 7.62 + 7.63 + Vector3() { x = y = z = 0.0; } 7.64 + Vector3(float a, float b, float c) { x = a; y = b; z = c; } 7.65 + 7.66 + void normalize() { float len = sqrt(x * x + y * y + z * z); x /= len; y /= len; z /= len; } 7.67 +}; 7.68 + 7.69 +struct Vector2 { 7.70 + float x, y; 7.71 + 7.72 + Vector2() { x = y = 0.0; } 7.73 + Vector2(float a, float b) { x = a; y = b; } 7.74 +}; 7.75 + 7.76 +struct obj_face { 7.77 + int elem; 7.78 + int v[4], n[4], t[4]; 7.79 +}; 7.80 + 7.81 +struct obj_file { 7.82 + string cur_obj, cur_mat; 7.83 + vector<Vector3> v, vn, vt; 7.84 + vector<obj_face> f; 7.85 +}; 7.86 + 7.87 +struct obj_mat { 7.88 + string name; // newmtl <name> 7.89 + Vector3 ambient, diffuse, specular; // Ka, Kd, Ks 7.90 + float shininess; // Ns 7.91 + float ior; // Ni 7.92 + float alpha; // d, Tr 7.93 + float refl; // Kr (my extesnsion) 7.94 + 7.95 + string tex_dif, tex_spec, tex_shin, tex_alpha; // map_Kd, map_Ks, map_Ns, map_d 7.96 + string tex_refl; // refl -type sphere|cube file 7.97 + string tex_bump; // bump 7.98 + 7.99 + obj_mat() { reset(); } 7.100 + 7.101 + void reset() { 7.102 + ambient = diffuse = Vector3(0.5, 0.5, 0.5); 7.103 + specular = Vector3(0.0, 0.0, 0.0); 7.104 + name = tex_dif = tex_spec = tex_shin = tex_alpha = tex_refl = tex_bump = ""; 7.105 + shininess = 0; 7.106 + ior = alpha = 1; 7.107 + refl = 0.0; 7.108 + } 7.109 +}; 7.110 + 7.111 +static bool read_materials(FILE *fp, vector<obj_mat> *vmtl); 7.112 +static Mesh *cons_mesh(obj_file *obj); 7.113 + 7.114 +static int get_cmd(char *str); 7.115 +static bool is_int(const char *str); 7.116 +static bool is_float(const char *str); 7.117 +static bool parse_vec(Vector3 *vec); 7.118 +static bool parse_color(Vector3 *col); 7.119 +static bool parse_face(obj_face *face); 7.120 +static const char *parse_map(); 7.121 + 7.122 +static bool find_file(char *res, int sz, const char *fname, const char *path = ".", const char *mode = "rb"); 7.123 +static const char *dirname(const char *str); 7.124 + 7.125 +static Vector3 operator -(const Vector3 &a, const Vector3 &b); 7.126 +static Vector3 cross(const Vector3 &a, const Vector3 &b); 7.127 + 7.128 +static map<string, int> matnames; 7.129 + 7.130 + 7.131 +#define FEQ(a, b) (fabs((a) - (b)) < 1e-8) 7.132 +bool Face::operator ==(const Face &f) const 7.133 +{ 7.134 + for(int i=0; i<3; i++) { 7.135 + for(int j=0; j<3; j++) { 7.136 + if(!FEQ(v[i].pos[j], f.v[i].pos[j])) { 7.137 + return false; 7.138 + } 7.139 + if(!FEQ(v[i].normal[j], f.v[i].normal[j])) { 7.140 + return false; 7.141 + } 7.142 + } 7.143 + if(!FEQ(normal[i], f.normal[i])) { 7.144 + return false; 7.145 + } 7.146 + } 7.147 + return true; 7.148 +} 7.149 + 7.150 +bool Scene::add_mesh(Mesh *m) 7.151 +{ 7.152 + // make sure triangles have material ids 7.153 + for(size_t i=0; i<m->faces.size(); i++) { 7.154 + m->faces[i].matid = m->matid; 7.155 + } 7.156 + meshes.push_back(m); 7.157 + return true; 7.158 +} 7.159 + 7.160 +int Scene::get_num_meshes() const 7.161 +{ 7.162 + return (int)meshes.size(); 7.163 +} 7.164 + 7.165 +int Scene::get_num_faces() const 7.166 +{ 7.167 + int num_faces = 0; 7.168 + for(size_t i=0; i<meshes.size(); i++) { 7.169 + num_faces += meshes[i]->faces.size(); 7.170 + } 7.171 + return num_faces; 7.172 +} 7.173 + 7.174 +int Scene::get_num_materials() const 7.175 +{ 7.176 + return (int)matlib.size(); 7.177 +} 7.178 + 7.179 +Material *Scene::get_materials() 7.180 +{ 7.181 + if(matlib.empty()) { 7.182 + return 0; 7.183 + } 7.184 + return &matlib[0]; 7.185 +} 7.186 + 7.187 +const Material *Scene::get_materials() const 7.188 +{ 7.189 + if(matlib.empty()) { 7.190 + return 0; 7.191 + } 7.192 + return &matlib[0]; 7.193 +} 7.194 + 7.195 + 7.196 +#define INVALID_IDX INT_MIN 7.197 + 7.198 +#define SEP " \t\n\r\v" 7.199 +#define BUF_SZ 512 7.200 + 7.201 +bool Scene::load(const char *fname) 7.202 +{ 7.203 + FILE *fp; 7.204 + 7.205 + if(!(fp = fopen(fname, "rb"))) { 7.206 + fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno)); 7.207 + return false; 7.208 + } 7.209 + 7.210 + bool res = load(fp); 7.211 + fclose(fp); 7.212 + return res; 7.213 +} 7.214 + 7.215 +bool Scene::load(FILE *fp) 7.216 +{ 7.217 + static int seq; 7.218 + char cur_name[16]; 7.219 + 7.220 + obj_file obj; 7.221 + 7.222 + sprintf(cur_name, "default%02d.obj", seq++); 7.223 + obj.cur_obj = cur_name; 7.224 + 7.225 + int prev_cmd = 0, obj_added = 0; 7.226 + for(;;) { 7.227 + Vector3 vec; 7.228 + obj_face face; 7.229 + 7.230 + char line[BUF_SZ]; 7.231 + fgets(line, sizeof line, fp); 7.232 + if(feof(fp)) { 7.233 + break; 7.234 + } 7.235 + 7.236 + char *tok; 7.237 + if(!(tok = strtok(line, SEP))) { 7.238 + continue; // ignore empty lines 7.239 + } 7.240 + 7.241 + int cmd; 7.242 + if((cmd = get_cmd(tok)) == -1) { 7.243 + continue; // ignore unknown commands ... 7.244 + } 7.245 + 7.246 + switch(cmd) { 7.247 + case CMD_V: 7.248 + if(!parse_vec(&vec)) { 7.249 + continue; 7.250 + } 7.251 + obj.v.push_back(vec); 7.252 + break; 7.253 + 7.254 + case CMD_VN: 7.255 + if(!parse_vec(&vec)) { 7.256 + continue; 7.257 + } 7.258 + obj.vn.push_back(vec); 7.259 + break; 7.260 + 7.261 + case CMD_VT: 7.262 + if(!parse_vec(&vec)) { 7.263 + continue; 7.264 + } 7.265 + vec.y = 1.0 - vec.y; 7.266 + obj.vt.push_back(vec); 7.267 + break; 7.268 + 7.269 + case CMD_O: 7.270 + case CMD_G: 7.271 + if(prev_cmd == CMD_O || prev_cmd == CMD_G) { 7.272 + break; // just in case we've got both of them in a row 7.273 + } 7.274 + /* if we have any previous data, group them up, add the object 7.275 + * and continue with the new one... 7.276 + */ 7.277 + if(!obj.f.empty()) { 7.278 + Mesh *mesh = cons_mesh(&obj); 7.279 + mesh->matid = matnames[obj.cur_mat]; 7.280 + add_mesh(mesh); 7.281 + obj_added++; 7.282 + 7.283 + obj.f.clear(); // clean the face list 7.284 + } 7.285 + if((tok = strtok(0, SEP))) { 7.286 + obj.cur_obj = tok; 7.287 + } else { 7.288 + sprintf(cur_name, "default%02d.obj", seq++); 7.289 + obj.cur_obj = cur_name; 7.290 + } 7.291 + break; 7.292 + 7.293 + case CMD_MTLLIB: 7.294 + if((tok = strtok(0, SEP))) { 7.295 + char path[PATH_MAX]; 7.296 + 7.297 + sprintf(path, ".:%s", dirname(tok)); 7.298 + if(!find_file(path, PATH_MAX, tok, path)) { 7.299 + fprintf(stderr, "material library not found: %s\n", tok); 7.300 + continue; 7.301 + } 7.302 + 7.303 + FILE *mfile; 7.304 + if(!(mfile = fopen(path, "rb"))) { 7.305 + fprintf(stderr, "failed to open material library: %s\n", path); 7.306 + continue; 7.307 + } 7.308 + 7.309 + // load all materials of the mtl file into a vector 7.310 + vector<obj_mat> vmtl; 7.311 + if(!read_materials(mfile, &vmtl)) { 7.312 + continue; 7.313 + } 7.314 + fclose(mfile); 7.315 + 7.316 + // and add them all to the scene 7.317 + for(size_t i=0; i<vmtl.size(); i++) { 7.318 + Material mat; 7.319 + 7.320 + mat.kd[0] = vmtl[i].diffuse.x; 7.321 + mat.kd[1] = vmtl[i].diffuse.y; 7.322 + mat.kd[2] = vmtl[i].diffuse.z; 7.323 + 7.324 + mat.ks[0] = vmtl[i].specular.x; 7.325 + mat.ks[1] = vmtl[i].specular.y; 7.326 + mat.ks[2] = vmtl[i].specular.z; 7.327 + 7.328 + mat.kt = 1.0 - vmtl[i].alpha; 7.329 + mat.kr = vmtl[i].refl; 7.330 + mat.spow = vmtl[i].shininess; 7.331 + 7.332 + matlib.push_back(mat); 7.333 + matnames[vmtl[i].name] = i; 7.334 + } 7.335 + } 7.336 + break; 7.337 + 7.338 + case CMD_USEMTL: 7.339 + if((tok = strtok(0, SEP))) { 7.340 + obj.cur_mat = tok; 7.341 + } else { 7.342 + obj.cur_mat = ""; 7.343 + } 7.344 + break; 7.345 + 7.346 + case CMD_F: 7.347 + if(!parse_face(&face)) { 7.348 + continue; 7.349 + } 7.350 + 7.351 + // convert negative indices to regular indices 7.352 + for(int i=0; i<4; i++) { 7.353 + if(face.v[i] < 0 && face.v[i] != INVALID_IDX) { 7.354 + face.v[i] = obj.v.size() + face.v[i]; 7.355 + } 7.356 + if(face.n[i] < 0 && face.n[i] != INVALID_IDX) { 7.357 + face.n[i] = obj.vn.size() + face.n[i]; 7.358 + } 7.359 + if(face.t[i] < 0 && face.t[i] != INVALID_IDX) { 7.360 + face.t[i] = obj.vt.size() + face.t[i]; 7.361 + } 7.362 + } 7.363 + 7.364 + // break quads into triangles if needed 7.365 + obj.f.push_back(face); 7.366 + if(face.elem == 4) { 7.367 + face.v[1] = face.v[2]; 7.368 + face.n[1] = face.n[2]; 7.369 + face.t[1] = face.t[2]; 7.370 + 7.371 + face.v[2] = face.v[3]; 7.372 + face.n[2] = face.n[3]; 7.373 + face.t[2] = face.t[3]; 7.374 + 7.375 + obj.f.push_back(face); 7.376 + } 7.377 + break; 7.378 + 7.379 + default: 7.380 + break; // ignore unknown commands 7.381 + } 7.382 + 7.383 + prev_cmd = cmd; 7.384 + } 7.385 + 7.386 + // reached end of file... 7.387 + if(!obj.f.empty()) { 7.388 + Mesh *mesh = cons_mesh(&obj); 7.389 + mesh->matid = matnames[obj.cur_mat]; 7.390 + add_mesh(mesh); 7.391 + obj_added++; 7.392 + } 7.393 + 7.394 + return obj_added > 0; 7.395 +} 7.396 + 7.397 +static Mesh *cons_mesh(obj_file *obj) 7.398 +{ 7.399 + Mesh *mesh; 7.400 + 7.401 + // need at least one of each element 7.402 + bool added_norm = false, added_tc = false; 7.403 + if(obj->vn.empty()) { 7.404 + obj->vn.push_back(Vector3(0, 0, 0)); 7.405 + added_norm = true; 7.406 + } 7.407 + if(obj->vt.empty()) { 7.408 + obj->vt.push_back(Vector3(0, 0, 0)); 7.409 + added_tc = true; 7.410 + } 7.411 + 7.412 + mesh = new Mesh; 7.413 + 7.414 + for(size_t i=0; i<obj->f.size(); i++) { 7.415 + Face face; 7.416 + Vector3 v[3]; 7.417 + 7.418 + for(int j=0; j<3; j++) { 7.419 + obj_face *f = &obj->f[i]; 7.420 + 7.421 + face.v[j].pos[0] = v[j].x = obj->v[f->v[j]].x; 7.422 + face.v[j].pos[1] = v[j].y = obj->v[f->v[j]].y; 7.423 + face.v[j].pos[2] = v[j].z = obj->v[f->v[j]].z; 7.424 + face.v[j].pos[3] = 0.0; 7.425 + 7.426 + int nidx = f->n[j] < 0 ? 0 : f->n[j]; 7.427 + face.v[j].normal[0] = obj->vn[nidx].x; 7.428 + face.v[j].normal[1] = obj->vn[nidx].y; 7.429 + face.v[j].normal[2] = obj->vn[nidx].z; 7.430 + face.v[j].normal[3] = 0.0; 7.431 + 7.432 + int tidx = f->t[j] < 0 ? 0 : f->t[j]; 7.433 + face.v[j].tex[0] = obj->vt[tidx].x; 7.434 + face.v[j].tex[1] = obj->vt[tidx].y; 7.435 + } 7.436 + 7.437 + Vector3 a = v[1] - v[0]; 7.438 + Vector3 b = v[2] - v[0]; 7.439 + Vector3 n = cross(a, b); 7.440 + n.normalize(); 7.441 + 7.442 + face.normal[0] = n.x; 7.443 + face.normal[1] = n.y; 7.444 + face.normal[2] = n.z; 7.445 + face.normal[3] = 0.0; 7.446 + 7.447 + mesh->faces.push_back(face); 7.448 + } 7.449 + 7.450 + if(added_norm) { 7.451 + obj->vn.pop_back(); 7.452 + } 7.453 + if(added_tc) { 7.454 + obj->vt.pop_back(); 7.455 + } 7.456 + 7.457 + return mesh; 7.458 +} 7.459 + 7.460 +static bool read_materials(FILE *fp, vector<obj_mat> *vmtl) 7.461 +{ 7.462 + obj_mat mat; 7.463 + 7.464 + for(;;) { 7.465 + char line[BUF_SZ]; 7.466 + fgets(line, sizeof line, fp); 7.467 + if(feof(fp)) { 7.468 + break; 7.469 + } 7.470 + 7.471 + char *tok; 7.472 + if(!(tok = strtok(line, SEP))) { 7.473 + continue; 7.474 + } 7.475 + 7.476 + int cmd; 7.477 + if((cmd = get_cmd(tok)) == -1) { 7.478 + continue; 7.479 + } 7.480 + 7.481 + switch(cmd) { 7.482 + case CMD_NEWMTL: 7.483 + // add the previous material, and start a new one 7.484 + if(mat.name.length() > 0) { 7.485 + printf("Adding material: %s\n", mat.name.c_str()); 7.486 + vmtl->push_back(mat); 7.487 + mat.reset(); 7.488 + } 7.489 + if((tok = strtok(0, SEP))) { 7.490 + mat.name = tok; 7.491 + } 7.492 + break; 7.493 + 7.494 + case CMD_KA: 7.495 + parse_color(&mat.ambient); 7.496 + break; 7.497 + 7.498 + case CMD_KD: 7.499 + parse_color(&mat.diffuse); 7.500 + break; 7.501 + 7.502 + case CMD_KS: 7.503 + parse_color(&mat.specular); 7.504 + break; 7.505 + 7.506 + case CMD_KR: 7.507 + if((tok = strtok(0, SEP)) && is_float(tok)) { 7.508 + mat.refl = atof(tok); 7.509 + } 7.510 + break; 7.511 + 7.512 + case CMD_NS: 7.513 + if((tok = strtok(0, SEP)) && is_float(tok)) { 7.514 + mat.shininess = atof(tok); 7.515 + } 7.516 + break; 7.517 + 7.518 + case CMD_NI: 7.519 + if((tok = strtok(0, SEP)) && is_float(tok)) { 7.520 + mat.ior = atof(tok); 7.521 + } 7.522 + break; 7.523 + 7.524 + case CMD_D: 7.525 + case CMD_TR: 7.526 + { 7.527 + Vector3 c; 7.528 + if(parse_color(&c)) { 7.529 + mat.alpha = cmd == CMD_D ? c.x : 1.0 - c.x; 7.530 + } 7.531 + } 7.532 + break; 7.533 + 7.534 + case CMD_MAP_KD: 7.535 + mat.tex_dif = parse_map(); 7.536 + break; 7.537 + 7.538 + default: 7.539 + break; 7.540 + } 7.541 + } 7.542 + 7.543 + if(mat.name.length() > 0) { 7.544 + printf("Adding material: %s\n", mat.name.c_str()); 7.545 + vmtl->push_back(mat); 7.546 + } 7.547 + return true; 7.548 +} 7.549 + 7.550 +static int get_cmd(char *str) 7.551 +{ 7.552 + char *s = str; 7.553 + while((*s = toupper(*s))) s++; 7.554 + 7.555 + for(int i=0; cmd_names[i]; i++) { 7.556 + if(strcmp(str, cmd_names[i]) == 0) { 7.557 + return i; 7.558 + } 7.559 + } 7.560 + return CMD_UNK; 7.561 +} 7.562 + 7.563 +static bool is_int(const char *str) 7.564 +{ 7.565 + char *tmp; 7.566 + strtol(str, &tmp, 10); 7.567 + return tmp != str; 7.568 +} 7.569 + 7.570 +static bool is_float(const char *str) 7.571 +{ 7.572 + char *tmp; 7.573 + strtod(str, &tmp); 7.574 + return tmp != str; 7.575 +} 7.576 + 7.577 +static bool parse_vec(Vector3 *vec) 7.578 +{ 7.579 + for(int i=0; i<3; i++) { 7.580 + char *tok; 7.581 + 7.582 + if(!(tok = strtok(0, SEP)) || !is_float(tok)) { 7.583 + if(i < 2) { 7.584 + return false; 7.585 + } 7.586 + vec->z = 0.0; 7.587 + } else { 7.588 + float v = atof(tok); 7.589 + 7.590 + switch(i) { 7.591 + case 0: 7.592 + vec->x = v; 7.593 + break; 7.594 + case 1: 7.595 + vec->y = v; 7.596 + break; 7.597 + case 2: 7.598 + vec->z = v; 7.599 + break; 7.600 + } 7.601 + } 7.602 + } 7.603 + return true; 7.604 +} 7.605 + 7.606 +static bool parse_color(Vector3 *col) 7.607 +{ 7.608 + for(int i=0; i<3; i++) { 7.609 + char *tok; 7.610 + 7.611 + if(!(tok = strtok(0, SEP)) || !is_float(tok)) { 7.612 + col->y = col->z = col->x; 7.613 + return i > 0 ? true : false; 7.614 + } 7.615 + 7.616 + float v = atof(tok); 7.617 + switch(i) { 7.618 + case 0: 7.619 + col->x = v; 7.620 + break; 7.621 + case 1: 7.622 + col->y = v; 7.623 + break; 7.624 + case 2: 7.625 + col->z = v; 7.626 + break; 7.627 + } 7.628 + } 7.629 + return true; 7.630 +} 7.631 + 7.632 +static bool parse_face(obj_face *face) 7.633 +{ 7.634 + char *tok[] = {0, 0, 0, 0}; 7.635 + face->elem = 0; 7.636 + 7.637 + for(int i=0; i<4; i++) { 7.638 + if((!(tok[i] = strtok(0, SEP)) || !is_int(tok[i]))) { 7.639 + if(i < 3) return false; // less than 3 verts? not a polygon 7.640 + } else { 7.641 + face->elem++; 7.642 + } 7.643 + } 7.644 + 7.645 + for(int i=0; i<4; i++) { 7.646 + char *subtok = tok[i]; 7.647 + 7.648 + if(!subtok || !*subtok || !is_int(subtok)) { 7.649 + if(i < 3) { 7.650 + return false; 7.651 + } 7.652 + face->v[i] = INVALID_IDX; 7.653 + } else { 7.654 + face->v[i] = atoi(subtok); 7.655 + if(face->v[i] > 0) face->v[i]--; /* convert to 0-based */ 7.656 + } 7.657 + 7.658 + while(subtok && *subtok && *subtok != '/') { 7.659 + subtok++; 7.660 + } 7.661 + if(subtok && *subtok && *++subtok && is_int(subtok)) { 7.662 + face->t[i] = atoi(subtok); 7.663 + if(face->t[i] > 0) face->t[i]--; /* convert to 0-based */ 7.664 + } else { 7.665 + face->t[i] = INVALID_IDX; 7.666 + } 7.667 + 7.668 + while(subtok && *subtok && *subtok != '/') { 7.669 + subtok++; 7.670 + } 7.671 + if(subtok && *subtok && *++subtok && is_int(subtok)) { 7.672 + face->n[i] = atoi(subtok); 7.673 + if(face->n[i] > 0) face->n[i]--; /* convert to 0-based */ 7.674 + } else { 7.675 + face->n[i] = INVALID_IDX; 7.676 + } 7.677 + } 7.678 + 7.679 + return true; 7.680 +} 7.681 + 7.682 +static const char *parse_map() 7.683 +{ 7.684 + char *tok, *prev = 0; 7.685 + 7.686 + while((tok = strtok(0, SEP))) { 7.687 + prev = tok; 7.688 + } 7.689 + 7.690 + return prev ? prev : ""; 7.691 +} 7.692 + 7.693 +static bool find_file(char *res, int sz, const char *fname, const char *path, const char *mode) 7.694 +{ 7.695 + FILE *fp; 7.696 + const char *beg, *end; 7.697 + int fnamelen = strlen(fname); 7.698 + 7.699 + beg = path; 7.700 + while(beg && *beg) { 7.701 + end = beg; 7.702 + while(*end && *end != ':') { 7.703 + end++; 7.704 + } 7.705 + 7.706 + int res_len = end - beg; 7.707 + char *pathname = (char*)alloca(res_len + fnamelen + 2); 7.708 + memcpy(pathname, beg, res_len); 7.709 + pathname[res_len] = 0; 7.710 + if(res_len) { 7.711 + strcat(pathname, "/"); 7.712 + } 7.713 + strcat(pathname, fname); 7.714 + 7.715 + if((fp = fopen(pathname, mode))) { 7.716 + fclose(fp); 7.717 + strncpy(res, pathname, sz); 7.718 + return true; 7.719 + } 7.720 + 7.721 + beg += res_len; 7.722 + if(*beg == ':') beg++; 7.723 + } 7.724 + return false; 7.725 +} 7.726 + 7.727 +static const char *dirname(const char *str) 7.728 +{ 7.729 + static char buf[PATH_MAX]; 7.730 + 7.731 + if(!str || !*str) { 7.732 + strcpy(buf, "."); 7.733 + } else { 7.734 + strncpy(buf, str, PATH_MAX); 7.735 + char *ptr = strrchr(buf, '/'); 7.736 + 7.737 + if(ptr && *ptr) { 7.738 + *ptr = 0; 7.739 + } else { 7.740 + strcpy(buf, "."); 7.741 + } 7.742 + } 7.743 + return buf; 7.744 +} 7.745 + 7.746 +static Vector3 operator -(const Vector3 &a, const Vector3 &b) 7.747 +{ 7.748 + return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); 7.749 +} 7.750 + 7.751 +static Vector3 cross(const Vector3 &a, const Vector3 &b) 7.752 +{ 7.753 + Vector3 res; 7.754 + res.x = a.y * b.z - a.z * b.y; 7.755 + res.y = a.z * b.x - a.x * b.z; 7.756 + res.z = a.x * b.y - a.y * b.x; 7.757 + return res; 7.758 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/scene.h Wed Aug 11 04:30:35 2010 +0100 8.3 @@ -0,0 +1,71 @@ 8.4 +#ifndef MESH_H_ 8.5 +#define MESH_H_ 8.6 + 8.7 +#include <vector> 8.8 + 8.9 +struct Vertex { 8.10 + float pos[4]; 8.11 + float normal[4]; 8.12 + float tex[4]; 8.13 + float padding[4]; 8.14 +}; 8.15 + 8.16 +struct Face { 8.17 + Vertex v[3]; 8.18 + float normal[4]; 8.19 + int matid; 8.20 + int padding[3]; 8.21 + 8.22 + bool operator ==(const Face &f) const; 8.23 +}; 8.24 + 8.25 +struct Material { 8.26 + float kd[4], ks[4]; 8.27 + float kr, kt; 8.28 + float spow; 8.29 + float padding; 8.30 +}; 8.31 + 8.32 +struct Mesh { 8.33 + std::vector<Face> faces; 8.34 + int matid; 8.35 +}; 8.36 + 8.37 +/*enum { 8.38 + KDAXIS_X, 8.39 + KDAXIS_Y, 8.40 + KDAXIS_Z 8.41 +}; 8.42 + 8.43 +#define KDCLEAR(node) ((node)->axis = -1) 8.44 +#define KDUSED(node) ((node)->axis >= 0) 8.45 +#define KDPARENT(x) ((x) >> 1) 8.46 +#define KDLEFT(x) ((x) << 1) 8.47 +#define KDRIGHT(x) (((x) << 1) + 1) 8.48 + 8.49 +struct KDNode { 8.50 + int axis; 8.51 + float pt; 8.52 +};*/ 8.53 + 8.54 +class Scene { 8.55 +public: 8.56 + std::vector<Mesh*> meshes; 8.57 + std::vector<Material> matlib; 8.58 + //std::vector<KDNode> kdtree; 8.59 + 8.60 + bool add_mesh(Mesh *m); 8.61 + int get_num_meshes() const; 8.62 + int get_num_materials() const; 8.63 + int get_num_faces() const; 8.64 + 8.65 + Material *get_materials(); 8.66 + const Material *get_materials() const; 8.67 + 8.68 + bool load(const char *fname); 8.69 + bool load(FILE *fp); 8.70 + 8.71 + //void build_kdtree(); 8.72 +}; 8.73 + 8.74 +#endif /* MESH_H_ */