John@15: #include nuclear@25: #include nuclear@22: #include "scene.h" nuclear@6: John@15: #define FEQ(a, b) (fabs((a) - (b)) < 1e-8) John@15: bool Face::operator ==(const Face &f) const John@15: { John@15: for(int i=0; i<3; i++) { John@15: for(int j=0; j<3; j++) { John@15: if(!FEQ(v[i].pos[j], f.v[i].pos[j])) { John@15: return false; John@15: } John@15: if(!FEQ(v[i].normal[j], f.v[i].normal[j])) { John@15: return false; John@15: } John@15: } John@15: if(!FEQ(normal[i], f.normal[i])) { John@15: return false; John@15: } John@15: } John@15: return true; John@15: } John@15: nuclear@25: float AABBox::calc_surface_area() const nuclear@25: { nuclear@25: float area1 = (max[0] - min[0]) * (max[1] - min[1]); nuclear@25: float area2 = (max[3] - min[3]) * (max[1] - min[1]); nuclear@25: float area3 = (max[0] - min[0]) * (max[3] - min[3]); nuclear@25: nuclear@25: return 2.0f * (area1 + area2 + area3); nuclear@25: } nuclear@25: nuclear@25: nuclear@24: Scene::Scene() nuclear@24: { nuclear@24: facebuf = 0; nuclear@24: num_faces = -1; nuclear@24: kdtree = 0; nuclear@24: } nuclear@24: nuclear@24: Scene::~Scene() nuclear@24: { nuclear@24: delete [] facebuf; nuclear@24: } nuclear@24: nuclear@13: bool Scene::add_mesh(Mesh *m) nuclear@13: { nuclear@13: // make sure triangles have material ids nuclear@13: for(size_t i=0; ifaces.size(); i++) { nuclear@13: m->faces[i].matid = m->matid; nuclear@13: } nuclear@24: nuclear@24: try { nuclear@24: meshes.push_back(m); nuclear@24: } nuclear@24: catch(...) { nuclear@24: return false; nuclear@24: } nuclear@24: nuclear@24: // invalidate facebuffer and count nuclear@24: delete [] facebuf; nuclear@24: facebuf = 0; nuclear@24: num_faces = -1; nuclear@24: nuclear@13: return true; nuclear@13: } nuclear@13: John@14: int Scene::get_num_meshes() const John@14: { John@14: return (int)meshes.size(); John@14: } John@14: nuclear@13: int Scene::get_num_faces() const nuclear@13: { nuclear@24: if(num_faces >= 0) { nuclear@24: return num_faces; nuclear@24: } nuclear@24: nuclear@24: num_faces = 0; nuclear@13: for(size_t i=0; ifaces.size(); nuclear@13: } nuclear@13: return num_faces; nuclear@13: } nuclear@13: John@14: int Scene::get_num_materials() const John@14: { John@14: return (int)matlib.size(); John@14: } John@14: John@14: Material *Scene::get_materials() John@14: { John@14: if(matlib.empty()) { John@14: return 0; John@14: } John@14: return &matlib[0]; John@14: } John@14: John@14: const Material *Scene::get_materials() const John@14: { John@14: if(matlib.empty()) { John@14: return 0; John@14: } John@14: return &matlib[0]; John@14: } nuclear@24: nuclear@24: const Face *Scene::get_face_buffer() const nuclear@24: { nuclear@24: if(facebuf) { nuclear@24: return facebuf; nuclear@24: } nuclear@24: nuclear@24: int num_meshes = get_num_meshes(); nuclear@24: nuclear@24: printf("constructing face buffer with %d faces (out of %d meshes)\n", get_num_faces(), num_meshes); nuclear@24: facebuf = new Face[num_faces]; nuclear@24: Face *fptr = facebuf; nuclear@24: nuclear@24: for(int i=0; ifaces.size(); j++) { nuclear@24: *fptr++ = meshes[i]->faces[j]; nuclear@24: } nuclear@24: } nuclear@24: return facebuf; nuclear@24: } nuclear@24: nuclear@25: static int build_kdtree(KDNode *kd); nuclear@25: static void free_kdtree(KDNode *node); nuclear@24: nuclear@24: void Scene::build_kdtree() nuclear@24: { nuclear@24: const Face *faces = get_face_buffer(); nuclear@24: int num_faces = get_num_faces(); nuclear@24: nuclear@25: printf("Constructing kd-tree out of %d faces ...\n", num_faces); nuclear@25: nuclear@25: free_kdtree(kdtree); nuclear@25: kdtree = new KDNode; nuclear@25: kdtree->left = kdtree->right = 0; nuclear@25: nuclear@25: /* Start the construction of the kdtree by adding all faces of the scene nuclear@25: * to the new root node. At the same time calculate the root's AABB. nuclear@25: */ nuclear@25: kdtree->aabb.min[0] = kdtree->aabb.min[1] = kdtree->aabb.min[2] = FLT_MAX; nuclear@25: kdtree->aabb.max[0] = kdtree->aabb.max[1] = kdtree->aabb.max[2] = -FLT_MAX; nuclear@25: nuclear@24: for(int i=0; iv[j].pos; nuclear@25: nuclear@25: // for each element (xyz) of the position vector ... nuclear@25: for(int k=0; k<3; k++) { nuclear@25: if(pos[k] < kdtree->aabb.min[k]) { nuclear@25: kdtree->aabb.min[k] = pos[k]; nuclear@25: } nuclear@25: if(pos[k] > kdtree->aabb.max[k]) { nuclear@25: kdtree->aabb.max[k] = pos[k]; nuclear@25: } nuclear@25: } nuclear@25: } nuclear@25: nuclear@25: kdtree->faces.push_back(face); // add the face nuclear@24: } nuclear@24: nuclear@25: // now proceed splitting the root recursively nuclear@25: ::build_kdtree(kdtree); nuclear@24: } nuclear@24: nuclear@25: static int build_kdtree(KDNode *kd) nuclear@24: { nuclear@25: if(kd->faces.empty()) { nuclear@25: return 0; nuclear@25: } nuclear@25: nuclear@25: // XXX cont. nuclear@25: return -1; nuclear@24: } nuclear@25: nuclear@25: static void free_kdtree(KDNode *node) nuclear@25: { nuclear@25: if(node) { nuclear@25: free_kdtree(node->left); nuclear@25: free_kdtree(node->right); nuclear@25: delete node; nuclear@25: } nuclear@25: }