From 6521936cdaa2132ee6860dfda335d0afbe958484 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Thu, 16 Jul 2020 17:02:49 +0200 Subject: Read collision meshes from OBJ files. Do not read meshes if the material has the Ignore flag set. --- src/model/objfile.cc | 128 +++++++++++++++++++++++++++++++++++---------------- src/model/objfile.h | 7 ++- 2 files changed, 93 insertions(+), 42 deletions(-) diff --git a/src/model/objfile.cc b/src/model/objfile.cc index 49a691f..323986b 100644 --- a/src/model/objfile.cc +++ b/src/model/objfile.cc @@ -34,6 +34,9 @@ OBJFile::OBJFile(std::string const &name) // reset counters obj_normalcount = 0; + + obj_collisionmodel = nullptr; + obj_load_clip = false; } OBJFile::~OBJFile() @@ -132,9 +135,11 @@ bool OBJFile::read() std::string materialname; material = 0; - if (line >> materialname) { - for(MaterialList::iterator it = obj_materiallist.begin(); it != obj_materiallist.end(); ++it) { - if( (*it).second->name() == materialname) { + if (line >> materialname) + { + for(MaterialList::iterator it = obj_materiallist.begin(); it != obj_materiallist.end(); ++it) + { + if( (*it).second->name().compare(materialname) == 0) { material = (*it).second; current_m = (*it).first; break; @@ -146,12 +151,12 @@ bool OBJFile::read() obj_materiallist[obj_materiallist.size()] = material; current_m = obj_materiallist.size()-1; } - } - else + } else { con_warn << objfile_name << " invalid material definition at line " << index_line << std::endl; + } - } else if (word.compare("v") == 0) { /* new wertex */ + } else if (word.compare("v") == 0) { /* new vertex */ float x, y, z; line >> x >> y >> z; @@ -159,14 +164,14 @@ bool OBJFile::read() obj_vertexlist[obj_vertexlist.size()] = v; obj_box.expand(*v * SCALE); - } else if (word.compare("vt") == 0) { /* wertex texture coordinate */ + } else if (word.compare("vt") == 0) { /* vertex texture coordinate */ float u, v; line >> u >> v; math::Vector2f *uv = new math::Vector2f(u, v); obj_uvlist[obj_uvlist.size()] = uv; - } else if (word.compare("vn") == 0) { /* wertex wormal */ + } else if (word.compare("vn") == 0) { /* vertex normal */ float x, y, z; line >> x >> y >> z; @@ -352,34 +357,64 @@ bool OBJFile::read() //Go through tri and quad lists and create fragments for each material size_t total_m = obj_materiallist.size(); - for(size_t i = 0; i <= total_m; i++) { + for(size_t i = 0; i < total_m; i++) + { material = obj_materiallist[i]; - fragment = new Fragment(Fragment::Triangles, material); - for(TriList::iterator it = obj_trilist.begin(); it != obj_trilist.end(); ++it) { - if((*it).first == i) { - fragment->add_vertex(((*it).second->v0() * SCALE) , (*it).second->n0(), (*it).second->t0(), false); - fragment->add_vertex(((*it).second->v1() * SCALE) , (*it).second->n1(), (*it).second->t1(), false); - fragment->add_vertex(((*it).second->v2() * SCALE) , (*it).second->n2(), (*it).second->t2(), false); + if (material->has_flag_clip()) // add mesh to the collision model if the material has the Clip flag set + { + CollisionMesh *collisionmesh = new CollisionMesh(); + + // add triangles to the collision mesh + for(TriList::iterator it = obj_trilist.begin(); it != obj_trilist.end(); ++it) + { + if((*it).first == i) + { + collisionmesh->add_triangle((*it).second->v0() * SCALE, (*it).second->v1() * SCALE, (*it).second->v2() * SCALE); + } } - } - - if( fragment->structural_size() + fragment->detail_size() > 0 ) - obj_fragmentgroup->add_fragment(fragment); - fragment = new Fragment(Fragment::Quads, material); - - for(QuadList::iterator it = obj_quadlist.begin(); it != obj_quadlist.end(); ++it) { - if((*it).first == i) { - fragment->add_vertex(((*it).second->v0() * SCALE) , (*it).second->n0(), (*it).second->t0(), false); - fragment->add_vertex(((*it).second->v1() * SCALE) , (*it).second->n1(), (*it).second->t1(), false); - fragment->add_vertex(((*it).second->v2() * SCALE) , (*it).second->n2(), (*it).second->t2(), false); - fragment->add_vertex(((*it).second->v3() * SCALE) , (*it).second->n3(), (*it).second->t3(), false); + for(QuadList::iterator it = obj_quadlist.begin(); it != obj_quadlist.end(); ++it) + { + if((*it).first == i) + { + collisionmesh->add_triangle((*it).second->v0() * SCALE, (*it).second->v1() * SCALE, (*it).second->v2() * SCALE); + collisionmesh->add_triangle((*it).second->v2() * SCALE, (*it).second->v3() * SCALE, (*it).second->v0() * SCALE); + } } + + obj_collisionmodel->add_mesh(collisionmesh); + } + else if (!material->has_flag_ignore()) // do not load meshes if the material has the Ignore flag + { + + fragment = new Fragment(Fragment::Triangles, material); + + for(TriList::iterator it = obj_trilist.begin(); it != obj_trilist.end(); ++it) { + if((*it).first == i) { + fragment->add_vertex(((*it).second->v0() * SCALE) , (*it).second->n0(), (*it).second->t0(), false); + fragment->add_vertex(((*it).second->v1() * SCALE) , (*it).second->n1(), (*it).second->t1(), false); + fragment->add_vertex(((*it).second->v2() * SCALE) , (*it).second->n2(), (*it).second->t2(), false); + } + } + + if( fragment->structural_size() + fragment->detail_size() > 0 ) + obj_fragmentgroup->add_fragment(fragment); + + fragment = new Fragment(Fragment::Quads, material); + + for(QuadList::iterator it = obj_quadlist.begin(); it != obj_quadlist.end(); ++it) { + if((*it).first == i) { + fragment->add_vertex(((*it).second->v0() * SCALE) , (*it).second->n0(), (*it).second->t0(), false); + fragment->add_vertex(((*it).second->v1() * SCALE) , (*it).second->n1(), (*it).second->t1(), false); + fragment->add_vertex(((*it).second->v2() * SCALE) , (*it).second->n2(), (*it).second->t2(), false); + fragment->add_vertex(((*it).second->v3() * SCALE) , (*it).second->n3(), (*it).second->t3(), false); + } + } + + if( fragment->structural_size() + fragment->detail_size() > 0 ) + obj_fragmentgroup->add_fragment(fragment); } - - if( fragment->structural_size() + fragment->detail_size() > 0 ) - obj_fragmentgroup->add_fragment(fragment); } return true; @@ -387,22 +422,34 @@ bool OBJFile::read() Model *OBJFile::load(const std::string &name) { + OBJFile objfile(name); - if (!objfile.is_open()) { - return 0; + return nullptr; } - if (!objfile.read()) { - return 0; - } - - if (!objfile.fragmentgroup()->size()) - return 0; - // create a new model Model *model = new Model(name); + // load clip into collision meshes + // if the model has been loaded before (e.g. on r_restart), the collision model won't be reloaded + objfile.obj_collisionmodel = CollisionModel::find(name); + if (!objfile.obj_collisionmodel) + { + objfile.obj_load_clip = true; + objfile.obj_collisionmodel = new CollisionModel(name); + CollisionModel::add(objfile.obj_collisionmodel); + } else { + objfile.obj_load_clip = false; + } + model->set_collisionmodel(objfile.obj_collisionmodel); + + if (!objfile.read() || !objfile.fragmentgroup()->size()) + { + con_warn << " " << objfile.name() << " empty model" << std::endl; + return model; + } + // center model around (0,0,0) and set the bounding box math::Vector3f obj_center((objfile.box().min() + objfile.box().max()) * 0.5f); model->model_box.assign( @@ -414,7 +461,8 @@ Model *OBJFile::load(const std::string &name) objfile.fragmentgroup()->set_location(obj_center * -1.0f); - for (FragmentGroup::Fragments::const_iterator fit = objfile.fragmentgroup()->fragments().begin(); fit != objfile.fragmentgroup()->fragments().end(); fit++) { + for (FragmentGroup::Fragments::const_iterator fit = objfile.fragmentgroup()->fragments().begin(); fit != objfile.fragmentgroup()->fragments().end(); ++fit) + { const Fragment *fragment = (*fit); if(fragment->type() == Fragment::Triangles) diff --git a/src/model/objfile.h b/src/model/objfile.h index 7db90bc..b8286dc 100644 --- a/src/model/objfile.h +++ b/src/model/objfile.h @@ -32,7 +32,7 @@ class OBJFile public: /** * @brief load a .obj file into a Model - * @param name name of the model to be loaded, without .obj extension or models/ prefix + * @param name name of the model to be loaded, without .obj extension. * If the file can not be read, load() returns the NULL-pointer */ static Model *load(std::string const &name); @@ -66,7 +66,7 @@ private: bool read(); /** - * @brief parse a line in the .obj file. + * @brief parse a line in the .obj file */ void readline(std::string const &line); @@ -112,6 +112,9 @@ private: FragmentGroup *obj_fragmentgroup; size_t obj_normalcount; + + bool obj_load_clip; + CollisionModel *obj_collisionmodel; }; } // namespace model -- cgit v1.2.3