From 324f5431245f2a550acddea70ea72770430a19d1 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 9 Aug 2009 16:34:38 +0000 Subject: initial .ase support --- src/model/Makefile.am | 7 +- src/model/asefile.cc | 295 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/model/asefile.h | 90 +++++++++++++++ src/model/map.cc | 9 +- src/model/map.h | 8 +- src/model/model.cc | 16 ++- src/model/triangle.cc | 31 +++++- src/model/triangle.h | 38 ++++++- 8 files changed, 473 insertions(+), 21 deletions(-) create mode 100644 src/model/asefile.cc create mode 100644 src/model/asefile.h (limited to 'src/model') diff --git a/src/model/Makefile.am b/src/model/Makefile.am index 81512ab..94b3c96 100644 --- a/src/model/Makefile.am +++ b/src/model/Makefile.am @@ -1,11 +1,12 @@ METASOURCES = AUTO -libmodel_la_SOURCES = classes.cc fragment.cc map.cc material.cc model.cc \ - plane.cc primitives.cc quad.cc triangle.cc vertexarray.cc +libmodel_la_SOURCES = asefile.cc classes.cc fragment.cc map.cc material.cc \ + model.cc plane.cc primitives.cc quad.cc triangle.cc vertexarray.cc libmodel_la_LDFLAGS = -avoid-version -no-undefined -lm noinst_LTLIBRARIES = libmodel.la -noinst_HEADERS = classes.h fragment.h map.h material.h model.h plane.h \ +noinst_HEADERS = asefile.h classes.h fragment.h map.h material.h model.h plane.h \ primitives.h quad.h triangle.h vertexarray.h INCLUDES = -I$(top_srcdir)/src + diff --git a/src/model/asefile.cc b/src/model/asefile.cc new file mode 100644 index 0000000..182c58c --- /dev/null +++ b/src/model/asefile.cc @@ -0,0 +1,295 @@ +/* + 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 diff --git a/src/model/asefile.h b/src/model/asefile.h new file mode 100644 index 0000000..bb731b7 --- /dev/null +++ b/src/model/asefile.h @@ -0,0 +1,90 @@ +/* + model/asefile.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + + +#ifndef __INCLUDED_MODEL_ASEFILE_H__ +#define __INCLUDED_MODEL_ASEFILE_H__ + +#include "math/vector3f.h" +#include "model/model.h" +#include "filesystem/filestream.h" + +#include +#include + +namespace model +{ + +/// class to parse the .ase file structure and load geometry data into a model +class ASEFile +{ +public: + /** + * @brief load a .ase file into a Model + * @param name name of the model to be loaded, without .ase extension or models/ prefix + * If the file can not be read, load() returns the NULL-pointer + */ + static Model *load(std::string const &name); + +private: + + typedef std::map VertexList; + + ASEFile(std::string const &name); + ~ASEFile(); + + /** + * @brief read *MESH_FACE_LIST + */ + bool read_mesh_face_list(std::istream &is); + + /** + * @brief read *MESH_VERTEX_LIST + */ + bool read_mesh_vertex_list(std::istream &is); + + /** + * @brief read *MESH + */ + bool read_mesh(std::istream &is); + + /** + * @brief read *GEOMOBJECT + */ + bool read_geom(std::istream &is); + + /** + * @brief read the .ase header + */ + bool read_header(std::istream &is); + + /** + * @brief read the .ase file + */ + bool read(); + + inline const std::string &name() const { return asefile_name; } + + inline const bool is_open() const { return asefile_ifs.is_open(); } + + std::string asefile_name; + + filesystem::IFileStream asefile_ifs; + + VertexList ase_vertexlist; + + math::Vector3f ase_maxbbox; + + math::Vector3f ase_minbbox; + + math::Vector3f ase_center; + + Model *model; +}; + +} // namespace model + +#endif // __INCLUDED_MODEL_ASEFILE_H__ diff --git a/src/model/map.cc b/src/model/map.cc index c2b184f..8165e3a 100644 --- a/src/model/map.cc +++ b/src/model/map.cc @@ -1,5 +1,5 @@ /* - filesystem/map.cc + model/map.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ @@ -15,6 +15,7 @@ #include #include +#include namespace model { @@ -71,7 +72,6 @@ bool Map::open(std::string const & mapname) mapfile_ifs.open(mapfile_name); if (!mapfile_ifs.is_open()) { - con_warn << "Could not open " << mapfile_name << "!\n"; return false; } return true; @@ -97,8 +97,6 @@ bool Map::getline() { using math::Vector3f; - char data[1024]; - last_read_was_classname = false; last_read_was_key = false; last_read_was_classend = false; @@ -108,6 +106,9 @@ bool Map::getline() if (!mapfile_ifs.is_open()) return false; + + char data[1024]; + memset(data, 0, sizeof(data)); if (mapfile_ifs.getline(data, 1023)) { line_number++; diff --git a/src/model/map.h b/src/model/map.h index d7b01d7..8dc688e 100644 --- a/src/model/map.h +++ b/src/model/map.h @@ -24,8 +24,10 @@ class Map { public: - /// load a .map file into a Model - /** @param name name of the model to be loaded, without .map extension or maps/ prefix + /** + * @brief load a .map file into a Model + * @param name name of the model to be loaded, without .map extension or maps/ prefix + * If the file can not be read, load() returns the NULL-pointer */ static Model *load(std::string const &name); @@ -114,7 +116,7 @@ private: return line_number; } - /// return true of the ini file is open for reading + /// return true of the map file is open for reading inline bool is_open() { return mapfile_ifs.is_open(); diff --git a/src/model/model.cc b/src/model/model.cc index 3ec75d7..3ed5a93 100644 --- a/src/model/model.cc +++ b/src/model/model.cc @@ -5,6 +5,7 @@ */ #include "sys/sys.h" +#include "model/asefile.h" #include "model/model.h" #include "model/map.h" #include "model/vertexarray.h" @@ -101,10 +102,19 @@ Model *Model::load(std::string const & name) { Model *model = find(name); if (!model) { + // try loading the .map model model = Map::load(name); - if (model) { - model_registry[model->name()] = model; - } + } + + if (!model) { + // if it can't be found, try the ase model + model = ASEFile::load(name); + } + + if (!model) { + con_warn << "Could not load maps/" << name << ".map or models/" << name << ".ase" << std::endl; + } else { + model_registry[model->name()] = model; } return model; diff --git a/src/model/triangle.cc b/src/model/triangle.cc index 162b68a..a649fdd 100644 --- a/src/model/triangle.cc +++ b/src/model/triangle.cc @@ -9,16 +9,35 @@ namespace model { -Triangle::Triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, - math::Vector3f const &normal, bool detail) : - triangle_v0(v0), - triangle_v1(v1), - triangle_v2(v2), - triangle_normal(normal) +Triangle::Triangle( + math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, + math::Vector3f const &normal, bool detail) : + triangle_v0(v0), + triangle_n0(normal), + triangle_v1(v1), + triangle_n1(normal), + triangle_v2(v2), + triangle_n2(normal), + triangle_normal(normal) { triangle_detail = detail; } +Triangle::Triangle(math::Vector3f const &v0, math::Vector3f const &n0, + math::Vector3f const &v1, math::Vector3f const &n1, + math::Vector3f const &v2, math::Vector3f const &n2, + math::Vector3f const &normal) : + triangle_v0(v0), + triangle_n0(n0), + triangle_v1(v1), + triangle_n1(n1), + triangle_v2(v2), + triangle_n2(n2), + triangle_normal(normal) +{ + triangle_detail = false; +} + Triangle::~Triangle() {} diff --git a/src/model/triangle.h b/src/model/triangle.h index 416a3e6..27abeed 100644 --- a/src/model/triangle.h +++ b/src/model/triangle.h @@ -17,9 +17,19 @@ namespace model class Triangle { public: - /// a new triangle with 3 vertices, a normal, color and a detail flag + /// a new triangle with 3 vertices, a normal and detail flag Triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, math::Vector3f const &normal, bool detail); + + /** + * @brief a new triangle with 3 vertices with normals and a face normal + * this constructor sets the detail flag to false + */ + Triangle( math::Vector3f const &v0, math::Vector3f const &n0, + math::Vector3f const &v1, math::Vector3f const &n1, + math::Vector3f const &v2, math::Vector3f const &n2, + math::Vector3f const &normal); + /// delete triangle ~Triangle(); @@ -41,23 +51,47 @@ public: return triangle_v0; } + /// triangle vertex 0 normal + inline math::Vector3f & n0() + { + return triangle_n0; + } + /// triangle vertex 1 inline math::Vector3f & v1() { return triangle_v1; } + + /// triangle vertex 1 normal + inline math::Vector3f & n1() + { + return triangle_n1; + } /// triangle vertex 2 inline math::Vector3f & v2() { return triangle_v2; } + + /// triangle vertex 0 normal + inline math::Vector3f & n2() + { + return triangle_n2; + } + private: math::Vector3f triangle_v0; + math::Vector3f triangle_n0; + math::Vector3f triangle_v1; + math::Vector3f triangle_n1; + math::Vector3f triangle_v2; - + math::Vector3f triangle_n2; + math::Vector3f triangle_normal; bool triangle_detail; }; -- cgit v1.2.3