diff options
Diffstat (limited to 'src/model')
-rw-r--r-- | src/model/asefile.cc | 13 | ||||
-rw-r--r-- | src/model/classes.cc | 21 | ||||
-rw-r--r-- | src/model/classes.h | 54 | ||||
-rw-r--r-- | src/model/fragment.cc | 11 | ||||
-rw-r--r-- | src/model/fragment.h | 18 | ||||
-rw-r--r-- | src/model/map.cc | 161 | ||||
-rw-r--r-- | src/model/map.h | 14 | ||||
-rw-r--r-- | src/model/material.cc | 1 | ||||
-rw-r--r-- | src/model/model.cc | 4 |
9 files changed, 216 insertions, 81 deletions
diff --git a/src/model/asefile.cc b/src/model/asefile.cc index 22fcd78..28c84cf 100644 --- a/src/model/asefile.cc +++ b/src/model/asefile.cc @@ -18,7 +18,6 @@ const float MAX_BOUNDS = 16384.0f; ASEFile::ASEFile(std::string const &name) { - asefile_name.assign("models/"); asefile_name.append(name); asefile_name.append(".ase"); @@ -90,7 +89,7 @@ bool ASEFile::read_mesh_vertex_list(std::istream &is) line >> firstword; if (firstword.compare("}") == 0) { - con_debug << count << " mesh vertices" << std::endl; + con_debug << " " << count << " mesh vertices" << std::endl; return true; @@ -428,9 +427,9 @@ Model * ASEFile::load(const std::string &name) Model *model = new Model(name); // default material - Material *material = Material::find("models/" + name); + Material *material = Material::find(name); if (!material) { - material = new Material("models/" + name); + material = new Material(name); Material::add(material); material->set_flags(Material::Texture); material->set_texture(material->name()); @@ -440,13 +439,13 @@ Model * ASEFile::load(const std::string &name) Fragment *fragment = new Fragment(Fragment::Triangles, material); FragmentGroup *group = new FragmentGroup(); group->set_type(FragmentGroup::None); - group->push_back(fragment); + group->add_fragment(fragment); // calculate model center math::Vector3f center((asefile.ase_minbbox + asefile.ase_maxbbox) * 0.5f); - //const float scale = SCALE; - const float scale = 0.125f; + const float scale = SCALE; + //const float scale = 0.125f; // caculate bounding box model->model_minbbox = (asefile.ase_minbbox - center) * scale; diff --git a/src/model/classes.cc b/src/model/classes.cc index 3907184..2a16bae 100644 --- a/src/model/classes.cc +++ b/src/model/classes.cc @@ -8,16 +8,6 @@ namespace model { -/* ---- class MapClass --------------------------------------------- */ - -MapClass::MapClass() -{ -} - -MapClass::~MapClass() -{ -} - /* ---- class Light ------------------------------------------------ */ Light::Light() : @@ -83,4 +73,15 @@ Dock::~Dock() { } +/* ---- class SubModel---------------------------------------------- */ + +SubModel::SubModel() +{ + submodel_scale = 1.0f; +} + +SubModel::~SubModel() +{ +} + } diff --git a/src/model/classes.h b/src/model/classes.h index c2b6a20..111d7d0 100644 --- a/src/model/classes.h +++ b/src/model/classes.h @@ -23,28 +23,6 @@ namespace model */ enum Cull { CullNone=0, CullBack=1, CullFront=2 }; -/* ---- class MapClass --------------------------------------------- */ - -class MapClass -{ -public: - MapClass(); - ~MapClass(); - - inline const math::Vector3f &location() const { return mapclass_location; } - - inline const math::Axis &axis() const { return mapclass_axis; } - - - inline void set_location(const math::Vector3f location) { mapclass_location.assign(location); } - - inline void set_axis(const math::Axis axis) { mapclass_axis.assign(axis); } - -private: - math::Vector3f mapclass_location; - math::Axis mapclass_axis; -}; - /* ---- class Light ------------------------------------------------ */ /// an exterior light @@ -243,6 +221,38 @@ public: float dock_radius; }; +/* ---- class SubModel --------------------------------------------- */ + +/// a submodel +class SubModel +{ +public: + SubModel(); + ~SubModel(); + + inline const std::string &name() const { return submodel_name; } + + inline const float scale() const { return submodel_scale; } + + inline const math::Vector3f &location() const { return submodel_location; } + + inline math::Axis &axis() { return submodel_axis; } + + inline void set_scale(const float scale) { submodel_scale = scale; } + + inline void set_name(const std::string &name) { submodel_name.assign(name); } + + inline void set_location(const math::Vector3f &location) { submodel_location.assign(location); } + + inline void set_axis(const math::Axis &axis) { submodel_axis.assign(axis); } + +private: + std::string submodel_name; + float submodel_scale; + math::Vector3f submodel_location; + math::Axis submodel_axis; +}; + } #endif // __INCLUDED_MODEL_CLASSES_H__ diff --git a/src/model/fragment.cc b/src/model/fragment.cc index 72d8e2a..8c3481c 100644 --- a/src/model/fragment.cc +++ b/src/model/fragment.cc @@ -16,6 +16,15 @@ namespace model Quads: the number of Quads is size/4 */ +Fragment::Fragment(const Fragment &other) +{ + fragment_type = other.fragment_type; + fragment_index = other.fragment_index; + fragment_structural_size = other.fragment_structural_size; + fragment_detail_size = other.fragment_detail_size; + fragment_material = other.fragment_material; +} + Fragment::Fragment(Type type, const Material *material) { fragment_type = type; @@ -53,6 +62,8 @@ size_t Fragment::add_vertex(math::Vector3f const & vertex, math::Vector3f const FragmentGroup::FragmentGroup() { group_type = None; + group_scale = 1.0f; + group_transform = false; } FragmentGroup::~FragmentGroup() diff --git a/src/model/fragment.h b/src/model/fragment.h index 9d992e1..0a9ca6a 100644 --- a/src/model/fragment.h +++ b/src/model/fragment.h @@ -26,6 +26,11 @@ public: /// create a new fragment Fragment(Type type, const Material *material); + + /** + * @brief copy constructor + */ + Fragment(const Fragment &other); /// add a vertex to the fragment size_t add_vertex(math::Vector3f const & vertex, math::Vector3f const &normal, bool detail); @@ -95,6 +100,10 @@ public: inline const float speed() const { return group_speed; } + inline const float scale() const { return group_scale; } + + inline const bool transform() const { return group_transform; } + inline void set_type(const Type type) { group_type = type; } @@ -104,6 +113,9 @@ public: inline void set_speed(const float speed) { group_speed = speed; } + inline void set_scale(const float scale) { group_scale = scale; } + + inline void set_transform(const bool transform) { group_transform = transform; } inline iterator begin() { return group_fragments.begin(); } @@ -111,7 +123,7 @@ public: inline const size_t size() const { return group_fragments.size(); } - inline void push_back(Fragment *fragment) { group_fragments.push_back(fragment); } + inline void add_fragment(Fragment *fragment) { group_fragments.push_back(fragment); } void clear(); @@ -121,11 +133,13 @@ private: Fragments group_fragments; math::Vector3f group_location; - math::Vector3f group_forward; math::Axis group_axis; Type group_type; float group_speed; + float group_scale; + + bool group_transform; }; } diff --git a/src/model/map.cc b/src/model/map.cc index 9cb5295..164be3e 100644 --- a/src/model/map.cc +++ b/src/model/map.cc @@ -31,20 +31,22 @@ const float MAX_BOUNDS = 16384; const float MIN_DELTA = 10e-10; -Map::Map() : map_center(0,0,0) +MapFile::MapFile() : map_center(0,0,0) { mapfile_name.clear(); map_brushes = 0; map_faces = 0; map_faces_detail = 0; + + warning_q2brush = false; } -Map::~Map() +MapFile::~MapFile() { clear_materials(); } -void Map::clear_materials() +void MapFile::clear_materials() { for (Materials::iterator mit = map_materials.begin(); mit != map_materials.end(); mit++) { // delete list of primitives @@ -53,9 +55,9 @@ void Map::clear_materials() map_materials.clear(); } -bool Map::open(std::string const & mapname) +bool MapFile::open(std::string const & mapname) { - + warning_q2brush = false; last_read_was_classname = false; last_read_was_key = false; key_current = ""; @@ -66,7 +68,6 @@ bool Map::open(std::string const & mapname) clear_materials(); - mapfile_name.assign("maps/"); mapfile_name.append(mapname); mapfile_name.append(".map"); @@ -78,22 +79,22 @@ bool Map::open(std::string const & mapname) } -bool Map::got_classname() const +bool MapFile::got_classname() const { return last_read_was_classname; } -bool Map::got_classname(const char * classnamelabel) const +bool MapFile::got_classname(const char * classnamelabel) const { return (last_read_was_classname && (classname_current.compare(classnamelabel) == 0)); } -bool Map::got_classend(const char * classnamelabel) const +bool MapFile::got_classend(const char * classnamelabel) const { return (last_read_was_classend && (classname_current.compare(classnamelabel) == 0)); } -bool Map::getline() +bool MapFile::getline() { using math::Vector3f; @@ -216,8 +217,10 @@ bool Map::getline() plane->detail() = true; // surface flags - if (!(linestream >> n)) + if (!(linestream >> n)) { n = 0; + warning_q2brush = true; + } plane->surface_flags() = n; planes.push_back(plane); @@ -234,7 +237,7 @@ bool Map::getline() return true; } -void Map::make_brushface(Plane *face) +void MapFile::make_brushface(Plane *face) { using math::Vector3f; @@ -517,7 +520,7 @@ void Map::make_brushface(Plane *face) vl.clear(); } -bool Map::got_key_string(const char * keylabel, std::string & valuestring) +bool MapFile::got_key_string(const char * keylabel, std::string & valuestring) { if (last_read_was_key && (key_current.compare(keylabel) == 0)) { valuestring.assign(value_current); @@ -527,7 +530,7 @@ bool Map::got_key_string(const char * keylabel, std::string & valuestring) } } -bool Map::got_key_vector3f(const char * keylabel, math::Vector3f & v) +bool MapFile::got_key_vector3f(const char * keylabel, math::Vector3f & v) { if (last_read_was_key && (key_current.compare(keylabel) == 0)) { std::istringstream is(value_current); @@ -543,7 +546,7 @@ bool Map::got_key_vector3f(const char * keylabel, math::Vector3f & v) } } -bool Map::got_key_float(const char * keylabel, float & f) +bool MapFile::got_key_float(const char * keylabel, float & f) { if (last_read_was_key && (key_current.compare(keylabel) == 0)) { std::istringstream is(value_current); @@ -556,7 +559,7 @@ bool Map::got_key_float(const char * keylabel, float & f) } } -bool Map::got_key_int(const char * keylabel, unsigned int & u) +bool MapFile::got_key_int(const char * keylabel, unsigned int & u) { if (last_read_was_key && (key_current.compare(keylabel) == 0)) { std::istringstream is(value_current); @@ -569,12 +572,12 @@ bool Map::got_key_int(const char * keylabel, unsigned int & u) } } -bool Map::got_key(const char * keylabel) +bool MapFile::got_key(const char * keylabel) { return (last_read_was_key && (key_current.compare(keylabel) == 0)); } -bool Map::got_key_angle(const char * keylabel, float & f) +bool MapFile::got_key_angle(const char * keylabel, float & f) { if (last_read_was_key && (key_current.compare(keylabel) == 0)) { std::istringstream is(value_current); @@ -589,7 +592,7 @@ bool Map::got_key_angle(const char * keylabel, float & f) } } -bool Map::got_key_color(const char * keylabel, math::Color & color) +bool MapFile::got_key_color(const char * keylabel, math::Color & color) { if (last_read_was_key && (key_current.compare(keylabel) == 0)) { std::istringstream is(value_current); @@ -610,12 +613,12 @@ bool Map::got_key_color(const char * keylabel, math::Color & color) } } -void Map::close() +void MapFile::close() { mapfile_ifs.close(); } -void Map::clear_bbox() +void MapFile::clear_bbox() { for (int i=0; i < 3; i++) { class_minbbox[i] = MAX_BOUNDS; @@ -626,7 +629,7 @@ void Map::clear_bbox() class_speed = 0; } -void Map::load_worldspawn(Model *model) +void MapFile::load_worldspawn(Model *model) { if (!map_materials.size()) return; @@ -642,22 +645,25 @@ void Map::load_worldspawn(Model *model) load_fragmentgroup(model, FragmentGroup::None); } -void Map::load_fragmentgroup(Model *model, const FragmentGroup::Type class_type) +void MapFile::load_fragmentgroup(Model *model, const FragmentGroup::Type class_type) { if (!VertexArray::instance() || VertexArray::instance()->overflow()) return; if (!map_materials.size()) return; + + FragmentGroup *group = new FragmentGroup(); if (class_type == FragmentGroup::Rotate) { if (class_speed == 0) { // default rotation speed 45 degrees per second class_speed = 45.0f; } + + group->set_transform(true); } - FragmentGroup *group = new FragmentGroup(); group->set_type(class_type); group->set_location((class_minbbox + class_maxbbox) / 2.0f - map_center); group->set_axis(class_axis); @@ -700,7 +706,7 @@ void Map::load_fragmentgroup(Model *model, const FragmentGroup::Type class_type) } // add the fragment to the group - group->push_back(fragment); + group->add_fragment(fragment); } // store quads @@ -738,7 +744,7 @@ void Map::load_fragmentgroup(Model *model, const FragmentGroup::Type class_type) } // add the fragment to the group - group->push_back(fragment); + group->add_fragment(fragment); } } @@ -747,25 +753,25 @@ void Map::load_fragmentgroup(Model *model, const FragmentGroup::Type class_type) model->add_group(group); } -void Map::unknown_value() const +void MapFile::unknown_value() const { con_warn << name() << " unknown value '" << value() << "' for '" << classname() << ":" << key() << "' at line " << line() << std::endl; } -void Map::unknown_key() const +void MapFile::unknown_key() const { con_warn << name() << " unknown key '" << classname() << ":" << key() << "' at line " << line() << std::endl; } -void Map::unknown_class() const +void MapFile::unknown_class() const { con_warn << name() << " unknown class '" << classname() << "' at line " << line() << std::endl; } -Model * Map::load(std::string const &name) +Model * MapFile::load(std::string const &name) { // open the .map file - Map mapfile; + MapFile mapfile; if (!mapfile.open(name)) { return 0; @@ -778,10 +784,17 @@ Model * Map::load(std::string const &name) Particles *particles = 0; Flare *flare = 0; Light *light = 0; + SubModel *submodel = 0; + + std::string modelname; + math::Vector3f location; + + typedef std::list<SubModel *> SubModelList; + SubModelList submodel_list; unsigned int u; float angle; - float r; + float r, s; std::string str; while (mapfile.getline()) { @@ -1019,6 +1032,46 @@ Model * Map::load(std::string const &name) } else if (mapfile.got_key()) { mapfile.unknown_key(); } + + } else if (mapfile.got_classname("misc_model")) { + + // new submodel + submodel = new SubModel(); + submodel_list.push_back(submodel); + + } else if (mapfile.classname().compare("misc_model") == 0) { + + // submodel attributes + if (mapfile.got_key_vector3f("origin", location)) { + submodel->set_location(location * SCALE); + continue; + + } else if (mapfile.got_key_string("model", modelname)) { + + // remove extension + if (modelname[modelname.size()-4] == '.') { + modelname.erase(modelname.size()-4); + } + + submodel->set_name(modelname); + continue; + + } else if (mapfile.got_key_float("angle", angle)) { + if (angle == ANGLEUP) { + submodel->axis().change_pitch(90.0f); + } else if (angle == ANGLEDOWN) { + submodel->axis().change_pitch(-90.0f); + } else { + submodel->axis().change_direction(angle); + } + + } else if (mapfile.got_key_float("modelscale", s)) { + if (s) { + submodel->set_scale(s); + } else { + submodel->set_scale(1.0f); + } + } } else if (mapfile.got_classname("fx_particles")) { @@ -1098,8 +1151,52 @@ Model * Map::load(std::string const &name) (*dit)->dock_location -= mapfile.map_center; } + // FIXME this will go wrong if a Rotate group is imported as submodel + for (SubModelList::iterator smit = submodel_list.begin(); smit != submodel_list.end(); smit++) { + submodel = (*smit); + Model *submodel_model = 0; + + if (submodel->name().size()) { + submodel_model = Model::load(submodel->name()); + } + + if (submodel_model) { + // copy fragmentgroups + for (Model::Groups::iterator git = submodel_model->groups().begin(); git != submodel_model->groups().end(); git++) { + FragmentGroup *groupsrc = (*git); + FragmentGroup *groupdst = new FragmentGroup(); + + groupdst->set_transform(true); + groupdst->set_type(groupsrc->type()); + groupdst->set_scale(groupsrc->scale() * submodel->scale()); + groupdst->set_speed(groupsrc->speed()); + groupdst->set_location(groupsrc->location() + (submodel->location() - mapfile.map_center)); + groupdst->set_axis(groupsrc->axis() * submodel->axis()); + + // copy fragments + for (FragmentGroup::iterator fit = groupsrc->begin(); fit != groupsrc->end(); fit++) { + Fragment *fragmentdst = new Fragment(*(*fit)); + groupdst->add_fragment(fragmentdst); + } + + if (groupdst->size()) { + model->add_group(groupdst); + } else { + delete groupdst; + } + } + + con_debug << " imported submodel '" << submodel->name() << "'" << std::endl; + } + + delete submodel; + + } + con_debug << " " << mapfile.name() << " " << mapfile.map_brushes << " brushes " << mapfile.map_faces << "/" << mapfile.map_faces_detail << " faces/detail " << std::endl; + if (mapfile.warning_q2brush) + con_warn << " quake2 style brushes detected" << std::endl; return model; } diff --git a/src/model/map.h b/src/model/map.h index 8dc688e..ed0b3e1 100644 --- a/src/model/map.h +++ b/src/model/map.h @@ -4,8 +4,8 @@ the terms of the GNU General Public License version 2 */ -#ifndef __INCLUDED_MODEL_MAP_H__ -#define __INCLUDED_MODEL_MAP_H__ +#ifndef __INCLUDED_MODEL_MAPFILE_H__ +#define __INCLUDED_MODEL_MAPFILE_H__ #include <string> #include <vector> @@ -20,7 +20,7 @@ namespace model { /// class to parse the .map file structure and load geometry data into a model -class Map +class MapFile { public: @@ -32,8 +32,8 @@ public: static Model *load(std::string const &name); private: - Map(); - ~Map(); + MapFile(); + ~MapFile(); /// tpye definition for a per-material list of Primitives typedef std::map<Material *, Primitives *> Materials; @@ -180,8 +180,10 @@ private: math::Vector3f map_center; Materials map_materials; + + bool warning_q2brush; }; } -#endif // __INCLUDED_MODEL_MAP_H__ +#endif // __INCLUDED_MODEL_MAPFILE_H__ diff --git a/src/model/material.cc b/src/model/material.cc index 7d278f9..c35740f 100644 --- a/src/model/material.cc +++ b/src/model/material.cc @@ -163,6 +163,7 @@ void Material::load_shader(const std::string &shadername) // texture name should not contain spaces if (linestream >> firstword) { + // FIXME remve extension material->set_texture(firstword); material->set_flags(Material::Texture); } else { diff --git a/src/model/model.cc b/src/model/model.cc index 3ed5a93..b02f127 100644 --- a/src/model/model.cc +++ b/src/model/model.cc @@ -103,7 +103,7 @@ Model *Model::load(std::string const & name) Model *model = find(name); if (!model) { // try loading the .map model - model = Map::load(name); + model = MapFile::load(name); } if (!model) { @@ -112,7 +112,7 @@ Model *Model::load(std::string const & name) } if (!model) { - con_warn << "Could not load maps/" << name << ".map or models/" << name << ".ase" << std::endl; + con_warn << "Could not open " << name << std::endl; } else { model_registry[model->name()] = model; } |