#include "loader.h" #include #include #include #include #include "../resourcemanager.h" #include #include #include #include "../sparrowrenderer/src/texture.h" #include std::string Loader::obj_directory = ""; std::string Loader::mtl_directory = ""; std::string Loader::tex_directory = ""; std::string* Loader::loadTextFile(const std::string &filename) { std::ifstream t(filename); std::string *str = new std::string(); t.seekg(0, std::ios::end); str->reserve(t.tellg()); t.seekg(0, std::ios::beg); str->assign((std::istreambuf_iterator(t)), std::istreambuf_iterator()); return str; } Image* Loader::loadImage(const std::string &filename, bool hasAlpha) { sf::Image sfImg; sfImg.loadFromFile(tex_directory+filename); Image* img = new Image(); img->depth = hasAlpha ? 32 : 24; img->width = sfImg.getSize().x; img->height = sfImg.getSize().y; int size = img->width*img->height*(img->depth/8); img->allocate(size); const sf::Uint8 *pixels = sfImg.getPixelsPtr(); if(hasAlpha) memcpy(img->pixels, pixels, size); else { sf::Uint8 *ptr = (sf::Uint8*)img->pixels; for(int i=0; iwidth*img->height; ++i) memcpy(ptr + i*3, pixels + i*4, 3); } return img; } std::vector Loader::loadMesh(const std::string &filename){ std::vector meshes; std::vector pos; std::vector norm; std::vector tex; std::string line; Material* defaultMat = RESOURCE_GET(Material, "default"); if(defaultMat == NULL) { defaultMat = new PhongMaterial(); RESOURCE_ADD(defaultMat,Material,"default"); } Material* currentMat = defaultMat; std::ifstream file(obj_directory + filename); if(!file.is_open()) { fprintf(stderr, "can't load %s.\n", filename.c_str()); return meshes; } Mesh* currentMesh = new Mesh(); meshes.push_back(currentMesh); currentMesh->setMaterial(currentMat); std::getline(file, line); while(!file.eof()) { if(line.length() == 0) // line vide { std::getline(file, line); continue; } switch(line[0]) { case 'v': //vertex attribute switch(line[1]) { case ' ': // vertex position { glm::vec3 p; std::sscanf(line.c_str(),"v %f %f %f",&(p.x),&(p.y),&(p.z)); pos.push_back(p); break; } case 't': // texCoord { glm::vec2 t; std::sscanf(line.c_str(),"vt %f %f",&(t.x),&(t.y)); tex.push_back(t); break; } case 'n': // normal { glm::vec3 n; std::sscanf(line.c_str(),"vn %f %f %f",&(n.x),&(n.y),&(n.z)); norm.push_back(n); break; } } break; case 'f': // face { int tab[9]; std::sscanf(line.c_str(),"f %d/%d/%d %d/%d/%d %d/%d/%d",tab,tab+1,tab+2,tab+3,tab+4,tab+5,tab+6,tab+7,tab+8); //TODO: check sscanf success int nb_vertices = currentMesh->positions3D.size(); currentMesh->addTriangle(nb_vertices, nb_vertices+1, nb_vertices+2); for(int i=0; i<3; ++i) { if(norm.size() == 0) { if(tex.size() == 0) currentMesh->addVertex(pos[tab[i]-1]); else currentMesh->addVertex(pos[tab[i]-1], tex[tab[i+1]-1]); } else { if(tex.size() == 0) currentMesh->addVertex(pos[tab[i]-1], norm[tab[i+2]-1]); else currentMesh->addVertex(pos[tab[i]-1], norm[tab[i+2]-1], tex[tab[i+1]-1]); } } } break; case 'g': currentMesh = new Mesh(); meshes.push_back(currentMesh); currentMesh->setMaterial(currentMat); break; case 'm': // mtllib { char mat_filename[256]; std::sscanf(line.c_str(),"mtllib %s",mat_filename); loadMTL(std::string(mat_filename)); break; } case 'u': { // usemtl char mat_name[256]; std::sscanf(line.c_str(),"usemtl %s",mat_name); std::string material_name(mat_name); currentMat = RESOURCE_GET(Material, material_name); if(currentMat == NULL) { fprintf(stderr, "cannot find any material named : %s.\n", material_name.c_str()); currentMat = new PhongMaterial(); RESOURCE_ADD(currentMat,Material,material_name); } currentMesh->setMaterial(currentMat); } break; default: case '#': // comment break; } std::getline(file,line); } for(std::size_t i=0; iindices.size() == 0) { meshes[i] = meshes.back(); meshes.pop_back(); --i; } } return meshes; } //move this to an utils file ? std::vector split(const std::string &line, char sep){ std::vector tokens; std::size_t start=0, end=0; while((end = line.find(sep,start)) != std::string::npos){ tokens.push_back(line.substr(start,end-start)); start=end+1; } tokens.push_back(line.substr(start)); return tokens; } //load MTL bool Loader::loadMTL(const std::string &filename) { std::string line; std::ifstream file(mtl_directory + filename); if(!file.is_open()) { fprintf(stderr, "can't load %s.\n", filename.c_str()); return false; } PhongMaterial* mat = NULL; bool hasNormalMap = false; std::getline(file,line); while(!file.eof()) { if(line.length() == 0) { std::getline(file,line); continue; } //QStringList tokens = line.split(' '); std::vector tokens = split(line,' '); if(tokens[0].substr(0,1) == "#") { // this is a comment } else if((tokens[0] == "newmtl") && tokens.size() == 2) { mat = new PhongMaterial(); RESOURCE_ADD(mat,Material,tokens[1]); } else if((tokens[0].compare("Ka") == 0) && tokens.size() == 4) { mat->ambient.r = std::stof(tokens[1]); mat->ambient.g = std::stof(tokens[2]); mat->ambient.b = std::stof(tokens[3]); } else if(tokens[0].compare("Kd") == 0 && tokens.size() == 4) { mat->diffuse.r = std::stof(tokens[1]); mat->diffuse.g = std::stof(tokens[2]); mat->diffuse.b = std::stof(tokens[3]); } else if(tokens[0].compare("Ks") == 0 && tokens.size() == 4) { mat->specular.r = std::stof(tokens[1]); mat->specular.g = std::stof(tokens[2]); mat->specular.b = std::stof(tokens[3]); } else if(tokens[0].compare("Ns") == 0 && tokens.size() == 2) { mat->shininess = std::stof(tokens[1]); } else if((tokens[0].substr(0,4) == "map_") && tokens.size() == 2) { if(tokens[0].compare("map_Ka") == 0){ mat->ambient_texture = RESOURCE_GET(Texture,tokens[1]); if (mat->ambient_texture == NULL){ mat->ambient_texture = new Texture(loadImage(tokens[1])); RESOURCE_ADD(mat->ambient_texture,Texture,tokens[1]); } } else if(tokens[0].compare("map_Kd") == 0) { mat->diffuse_texture = RESOURCE_GET(Texture,tokens[1]); if (mat->diffuse_texture == NULL){ mat->diffuse_texture = new Texture(loadImage(tokens[1])); RESOURCE_ADD(mat->diffuse_texture,Texture,tokens[1]); } } else if(tokens[0].compare("map_Ks") == 0) { mat->specular_texture = RESOURCE_GET(Texture,tokens[1]); if (mat->specular_texture == NULL){ mat->specular_texture = new Texture(loadImage(tokens[1])); RESOURCE_ADD(mat->specular_texture,Texture,tokens[1]); } } else if(tokens[0].compare("map_Normal") == 0) { mat->normal_map = RESOURCE_GET(Texture,tokens[1]); if (mat->normal_map == NULL){ mat->normal_map = new Texture(loadImage(tokens[1])); RESOURCE_ADD(mat->normal_map,Texture,tokens[1]); } hasNormalMap = true; } else if(tokens[0].compare("map_d") == 0) { mat->alpha_mask = RESOURCE_GET(Texture,tokens[1]); if (mat->alpha_mask == NULL){ mat->alpha_mask = new Texture(loadImage(tokens[1])); RESOURCE_ADD(mat->alpha_mask,Texture,tokens[1]); } } else fprintf(stderr, "unsupported material property : \"%s\"\n", tokens[0].c_str()); } else fprintf(stderr, "unsupported material property : \"%s\"\n", tokens[0].c_str()); std::getline(file,line); } return hasNormalMap; } void Loader::setObjDirectory(std::string dir_){ obj_directory = dir_; } void Loader::setMtlDirectory(std::string dir_){ mtl_directory = dir_; } void Loader::setTexDirectory(std::string dir_){ tex_directory = dir_; } /* //glfinish void temp_glfinish(){ for(std::size_t i=0; iinitGL(); todos[i].target = images[i]->texture; delete images[i]; } } } */