/* model/asefile.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ #include "sys/sys.h" #include "model/asefile.h" #include #include namespace model { // max geometry bounds const float MAX_BOUNDS = 16384.0f; ASEFile::ASEFile(std::string const &name) { asefile_name.assign("models/"); asefile_name.append(name); asefile_name.append(".ase"); asefile_ifs.open(asefile_name); for (int i=0; i < 3; i++) { ase_minbbox[i] = MAX_BOUNDS; ase_maxbbox[i] = -MAX_BOUNDS; } } ASEFile::~ASEFile() { ase_vertexlist.clear(); if (asefile_ifs.is_open()) asefile_ifs.close(); } bool ASEFile::read_header(std::istream &is) { if (!is.good()) { return false; } char data[1024]; memset(data, 0, sizeof(data)); if (!is.getline(data, sizeof(data) -1 )) { return false; } std::istringstream line(data); std::string word; line >> word; if (!word.compare("*3DSMAX_ASCIIEXPORT") == 0) { return false; } return true; } bool ASEFile::read_mesh_face_list(std::istream &is) { Material *material = Material::find("ase_placeholder"); if (!material) { material = new Material("ase_placeholder"); Material::add(material); //material->set_color(math::Color(0.8, 0.8f, 0.8f)); material->set_flags(Material::Primary); } Fragment *fragment = new Fragment(Fragment::Triangles, material); FragmentGroup *group = new FragmentGroup(); group->set_type(FragmentGroup::None); group->push_back(fragment); size_t count = 0; char data[1024]; memset(data, 0, sizeof(data)); while (is.getline(data, sizeof(data) -1 )) { std::istringstream line(data); std::string word; line >> word; if (word.compare("}") == 0) { con_debug << count << " mesh faces" << std::endl; model->add_group(group); return true; } else if ( word.compare("*MESH_FACE") == 0) { size_t a, b, c; if ( (line >> word) && (line >> word) && (line >> a) && (line >> word) && (line >> b) && (line >> word) && (line >> c)) { fragment->add_vertex(ase_vertexlist[a], ase_vertexlist[a], false); fragment->add_vertex(ase_vertexlist[b], ase_vertexlist[b], false); fragment->add_vertex(ase_vertexlist[c], ase_vertexlist[c], false); model->model_tris_count++; model->model_tris_detail_count++; } count++; } } delete group; return false; } bool ASEFile::read_mesh_vertex_list(std::istream &is) { size_t count = 0; char data[1024]; memset(data, 0, sizeof(data)); while (is.getline(data, sizeof(data) -1 )) { std::istringstream line(data); std::string firstword; line >> firstword; if (firstword.compare("}") == 0) { con_debug << count << " mesh vertices" << std::endl; return true; } else if ( firstword.compare("*MESH_VERTEX") == 0) { size_t index; float x, y, z; if (line >> index >> x >> y >> z) { math::Vector3f v(x, y, z); ase_vertexlist[index] = v; for (size_t i = 0; i < 3; i++) { if (v[i] > ase_maxbbox[i]) { ase_maxbbox[i] = v[i]; } if (v[i] < ase_minbbox[i]) { ase_minbbox[i] = v[i]; } } count++; } } } return false; } bool ASEFile::read_mesh(std::istream &is) { char data[1024]; memset(data, 0, sizeof(data)); int level = 1; ase_vertexlist.clear(); while (is.getline(data, sizeof(data) -1 )) { std::istringstream line(data); std::string word; line >> word; if ((level == 1 ) && (word.compare("*MESH_VERTEX_LIST") == 0)) { if ((line >> word) && (word.compare("{") == 0)) { con_debug << " " << name() << " *MESH_VERTEX_LIST" << std::endl; read_mesh_vertex_list(is); } } else if ((level == 1 ) && (word.compare("*MESH_FACE_LIST") == 0)) { if ((line >> word) && (word.compare("{") == 0)) { con_debug << " " << name() << " *MESH_FACE_LIST" << std::endl; read_mesh_face_list(is); } } else { do { if (word.compare("{") == 0) { level++; } else if (word.compare("}") == 0) { level--; } } while (line >> word); } if (level == 0) return true; } return false; } bool ASEFile::read_geom(std::istream &is) { char data[1024]; memset(data, 0, sizeof(data)); int level = 1; while (is.getline(data, sizeof(data) -1 )) { std::istringstream line(data); std::string word; line >> word; if ((level == 1 ) && (word.compare("*MESH") == 0)) { if ((line >> word) && (word.compare("{") == 0)) { con_debug << " " << name() << " " << "*MESH" << std::endl; read_mesh(is); } } else { do { if (word.compare("{") == 0) { level++; } else if (word.compare("}") == 0) { level--; } } while (line >> word); } if (level == 0) return true; } return false; } bool ASEFile::read() { if (!read_header(asefile_ifs)) { con_warn << name() << ": not a valid ASE file!\n"; return 0; } char data[1024]; memset(data, 0, sizeof(data)); while (asefile_ifs.getline(data, sizeof(data) -1 )) { std::istringstream line(data); std::string word; line >> word; if (word.compare("*GEOMOBJECT") == 0) { if ((line >> word) && (word.compare("{") == 0)) { con_debug << " " << name() << " " << "*GEOMOBJECT" << std::endl; read_geom(asefile_ifs); } } } // TODO CENTER model->model_minbbox = ase_minbbox; model->model_maxbbox = ase_maxbbox; model->model_radius = math::max(ase_minbbox.length(), ase_maxbbox.length()); return true; } Model * ASEFile::load(const std::string &name) { ASEFile asefile(name); if (!asefile.is_open()) { return 0; } asefile.model = new Model(name); con_debug << " " << asefile.name() << std::endl; if (!asefile.read()) { delete asefile.model; asefile.model = 0; } return asefile.model; } } // namespace model