From c3097a768077fa9251a70de10bd29aff3c8553e1 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Fri, 15 Oct 2010 13:02:33 +0000 Subject: added parsing of ASE submaterial definitions --- src/model/asefile.cc | 169 ++++++++++++++++++++++++++++++++++++++------------ src/model/asefile.h | 16 ++++- src/model/triangle.cc | 2 + src/model/triangle.h | 11 ++++ 4 files changed, 156 insertions(+), 42 deletions(-) (limited to 'src/model') diff --git a/src/model/asefile.cc b/src/model/asefile.cc index 657d73c..d94f103 100644 --- a/src/model/asefile.cc +++ b/src/model/asefile.cc @@ -53,10 +53,17 @@ ASEFile::~ASEFile() } ase_facelist.clear(); - for (MaterialList::iterator it = ase_materiallist.begin(); it != ase_materiallist.end(); it++) { - (*it).second = 0; + for (MaterialList::iterator it = ase_materials.begin(); it != ase_materials.end(); it++) { + SubMaterialList *submaterials = (*it).second; + + for (SubMaterialList::iterator smit = submaterials->begin(); smit != submaterials->end(); smit++) { + (*smit).second = 0; + } + submaterials->clear(); + delete submaterials; + (*it).second = 0; } - ase_materiallist.clear(); + ase_materials.clear(); if (asefile_ifs.is_open()) asefile_ifs.close(); @@ -86,7 +93,7 @@ bool ASEFile::read_header(std::istream &is) return true; } -Material *ASEFile::read_material(std::istream &is) +Material *ASEFile::read_submaterial(std::istream &is) { Material *material = 0; char data[1024]; @@ -107,16 +114,6 @@ Material *ASEFile::read_material(std::istream &is) while ((line.get(c)) && (c != '"')) n += c; - // ignore caulk - if (n.compare("common/caulk") == 0) { - material = 0; - continue; - } - if (n.compare("textures/common/caulk") == 0) { - material = 0; - continue; - } - // find material material = Material::find(n); if (!material) { @@ -124,7 +121,7 @@ Material *ASEFile::read_material(std::istream &is) Material::add(material); material->set_texture(material->name()); } - + } else { do { if (word.compare("{") == 0) { @@ -135,13 +132,80 @@ Material *ASEFile::read_material(std::istream &is) } while (line >> word); } - if (level == 0) + if (level == 0) { return material; + } } return material; } +ASEFile::SubMaterialList *ASEFile::read_material(std::istream &is) +{ + SubMaterialList *submaterials = new SubMaterialList; + std::string materialname; + + char data[1024]; + memset(data, 0, sizeof(data)); + int level = 1; + size_t index = 0; + + while (is.getline(data, sizeof(data) - 1)) { + + std::istringstream line(data); + std::string word; + line >> word; + + if ((level == 1) && (word.compare("*MATERIAL_NAME") == 0)) { + // read material name + std::string n; + char c; + while ((line.get(c)) && (c != '"')); + while ((line.get(c)) && (c != '"')) + n += c; + + materialname.assign(n); + + } else if ((level == 1) && (word.compare("*SUBMATERIAL") == 0)) { + + if ((line >> index) && (line >> word) && (word.compare("{") == 0)) { + // this material defines submaterials, we ignore the parent definition + materialname.clear(); + + // add material to the submaterial list + (*submaterials)[index] = read_submaterial(is); + } + + } else { + do { + if (word.compare("{") == 0) { + level++; + } else if (word.compare("}") == 0) { + level--; + } + } while (line >> word); + } + + if (level == 0) { + + if (materialname.size()) { + // no submaterials, add a single material to the submaterial list + Material *material = Material::find(materialname); + if (!material) { + material = new Material(materialname); + Material::add(material); + material->set_texture(materialname); + } + (*submaterials)[0] = material; + } + + return submaterials; + } + } + + return submaterials; +} + bool ASEFile::read_material_list(std::istream &is) { char data[1024]; @@ -158,8 +222,8 @@ bool ASEFile::read_material_list(std::istream &is) if ((level == 1) && (word.compare("*MATERIAL") == 0)) { if ((line >> index) && (line >> word) && (word.compare("{") == 0)) { // add material to the ase material list - ase_materiallist[index] = read_material(is); - //con_debug << " " << name() << " " << "*MATERIAL " << index << " " << ase_materiallist[index]->name() << std::endl; + ase_materials[index] = read_material(is); + //con_debug << " " << name() << " " << "*MATERIAL " << index << " " << ase_materials[index]->name() << std::endl; } } else { @@ -237,17 +301,28 @@ bool ASEFile::read_mesh_face_list(std::istream &is) (line >> word) && (line >> a) && (line >> word) && (line >> b) && (line >> word) && (line >> c)) { - + + size_t index; + if (facestr.size() && facestr[facestr.size()-1] == ':') { facestr.erase(facestr.size() - 1); } - - size_t index; + std::istringstream faceindexstr(facestr); - faceindexstr >> index; - - Triangle *triangle = new Triangle(*ase_vertexlist[a], *ase_vertexlist[b], *ase_vertexlist[c]); - ase_facelist[index] = triangle; + if (faceindexstr >> index) { + Triangle *triangle = new Triangle(*ase_vertexlist[a], *ase_vertexlist[b], *ase_vertexlist[c]); + ase_facelist[index] = triangle; + + while (line >> word) { + if (word.compare("*MESH_MTLID") == 0) { + size_t submaterial_index = 0; + if (line >> submaterial_index) { + triangle->set_material_index(submaterial_index); + } + } + } + } + } ase_facecount++; } @@ -472,7 +547,7 @@ bool ASEFile::read_geom(std::istream &is) char data[1024]; memset(data, 0, sizeof(data)); int level = 1; - Material *material = 0; + SubMaterialList *submateriallist = 0; while (is.getline(data, sizeof(data) - 1)) { @@ -492,9 +567,11 @@ bool ASEFile::read_geom(std::istream &is) //con_debug << " " << name() << " " << "*MATERIAL_REF " << index << std::endl; // find the Material for index - MaterialList::iterator it = ase_materiallist.find(index); - if (it != ase_materiallist.end()) { - material = (*it).second; + MaterialList::iterator it = ase_materials.find(index); + if (it != ase_materials.end()) { + submateriallist = (*it).second; + } else { + submateriallist = 0; } } } else { @@ -510,16 +587,30 @@ bool ASEFile::read_geom(std::istream &is) if (level == 0) { // import only if the material is defined and there actually are triangles to import - if (material && ase_facelist.size()) { - // load GEOMOBJECT triangles in a model fragment - Fragment *fragment = new Fragment(Fragment::Triangles, material); - ase_fragmentgroup->add_fragment(fragment); - - for (FaceList::iterator it = ase_facelist.begin(); it != ase_facelist.end(); it++) { - Triangle *triangle = (*it).second; - fragment->add_vertex((triangle->v0() * SCALE) , triangle->n0(), triangle->t0(), false); - fragment->add_vertex((triangle->v1() * SCALE) , triangle->n1(), triangle->t1(), false); - fragment->add_vertex((triangle->v2() * SCALE) , triangle->n2(), triangle->t2(), false); + if (submateriallist && ase_facelist.size()) { + + // iterate submaterial list, create a fragment per material + for (SubMaterialList::iterator smit = submateriallist->begin(); smit != submateriallist->end(); smit++) { + size_t submaterial_index = (*smit).first; + Material *material = (*smit).second; + + // load GEOMOBJECT triangles with matching material into the fragment + Fragment *fragment = new Fragment(Fragment::Triangles, material); + for (FaceList::iterator it = ase_facelist.begin(); it != ase_facelist.end(); it++) { + + Triangle *triangle = (*it).second; + if (triangle->material_index() == submaterial_index) { + fragment->add_vertex((triangle->v0() * SCALE) , triangle->n0(), triangle->t0(), false); + fragment->add_vertex((triangle->v1() * SCALE) , triangle->n1(), triangle->t1(), false); + fragment->add_vertex((triangle->v2() * SCALE) , triangle->n2(), triangle->t2(), false); + } + } + + if (fragment->structural_size() + fragment->detail_size() > 0) { + ase_fragmentgroup->add_fragment(fragment); + } else { + delete fragment; + } } } diff --git a/src/model/asefile.h b/src/model/asefile.h index d8e3aea..9e3fea6 100644 --- a/src/model/asefile.h +++ b/src/model/asefile.h @@ -34,10 +34,15 @@ public: static Model *load(std::string const &name); private: + /** + * @brief type definition for a list of submaterials in the ASE file + */ + typedef std::map SubMaterialList; + /** * @brief type definition for a list of materials in the ASE file */ - typedef std::map MaterialList; + typedef std::map MaterialList; /** * @brief type definition for a list of vertices in a GEOMOBJECT @@ -52,10 +57,15 @@ private: ASEFile(std::string const &name); ~ASEFile(); + /** + * @brief read *SUBMATERIAL + */ + Material *read_submaterial(std::istream &is); + /** * @brief read *MATERIAL */ - Material *read_material(std::istream &is); + SubMaterialList *read_material(std::istream &is); /** * @brief read *MATERIAL_LIST @@ -142,7 +152,7 @@ private: FaceList ase_facelist; - MaterialList ase_materiallist; + MaterialList ase_materials; math::Vector3f ase_maxbbox; diff --git a/src/model/triangle.cc b/src/model/triangle.cc index 0fb7224..47b5ac3 100644 --- a/src/model/triangle.cc +++ b/src/model/triangle.cc @@ -15,6 +15,7 @@ Triangle::Triangle(const math::Vector3f &v0, const math::Vector3f &v1, const mat triangle_v2(v2) { triangle_detail = false; + triangle_material_index = 0; } Triangle::Triangle(const math::Vector3f &v0, const math::Vector3f &v1, const math::Vector3f &v2, const math::Vector3f &normal, const bool detail) : @@ -27,6 +28,7 @@ Triangle::Triangle(const math::Vector3f &v0, const math::Vector3f &v1, const ma triangle_normal(normal) { triangle_detail = detail; + triangle_material_index = 0; } Triangle::~Triangle() diff --git a/src/model/triangle.h b/src/model/triangle.h index 06a8810..d07f67d 100644 --- a/src/model/triangle.h +++ b/src/model/triangle.h @@ -86,6 +86,16 @@ public: inline math::Vector3f &normal() { return triangle_normal; } + + /// material inde + inline size_t material_index() const { + return triangle_material_index; + } + + /// set material index + inline void set_material_index(const size_t index) { + triangle_material_index = index; + } private: @@ -103,6 +113,7 @@ private: math::Vector3f triangle_normal; bool triangle_detail; + size_t triangle_material_index; }; } -- cgit v1.2.3