From f36ec64b08c791e7b907ed8efd9a2baa44e7f8fd Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sat, 20 Dec 2008 14:54:17 +0000 Subject: initial support for func_rotate and friends --- src/model/fragment.cc | 1 + src/model/fragment.h | 16 +++++- src/model/map.cc | 65 ++++++++++++++++-------- src/model/map.h | 5 +- src/model/model.cc | 20 ++++++-- src/model/model.h | 15 ++++-- src/render/draw.cc | 133 ++++++++++++++++++++++++++++---------------------- 7 files changed, 168 insertions(+), 87 deletions(-) (limited to 'src') diff --git a/src/model/fragment.cc b/src/model/fragment.cc index db34fdb..044e232 100644 --- a/src/model/fragment.cc +++ b/src/model/fragment.cc @@ -41,6 +41,7 @@ size_t Fragment::add_vertex(math::Vector3f const & vertex, math::Vector3f const FragmentGroup::FragmentGroup() { + group_type = None; } FragmentGroup::~FragmentGroup() diff --git a/src/model/fragment.h b/src/model/fragment.h index 409bb97..fcdeca3 100644 --- a/src/model/fragment.h +++ b/src/model/fragment.h @@ -74,12 +74,17 @@ private: class FragmentGroup { public: + enum Type {None = 0, Rotate = 1, Door = 2 }; + typedef std::list::iterator iterator; FragmentGroup(); + ~FragmentGroup(); - void clear(); + inline const math::Vector3f &location() const { return group_location; } + + inline const Type type() const { return group_type; } inline iterator begin() { return group_fragments.begin(); } @@ -89,11 +94,20 @@ public: inline void push_back(Fragment *fragment) { group_fragments.push_back(fragment); } + inline void set_location(const math::Vector3f &location) { group_location.assign(location); } + + inline void set_type(const Type type) { group_type = type; } + + void clear(); private: /// type definition for a list of model fragments typedef std::list Fragments; Fragments group_fragments; + math::Vector3f group_location; + math::Vector3f group_forward; + + Type group_type; }; } diff --git a/src/model/map.cc b/src/model/map.cc index f2c519f..71b0dda 100644 --- a/src/model/map.cc +++ b/src/model/map.cc @@ -242,6 +242,14 @@ bool Map::getline() return true; } +void Map::clear_bbox() +{ + for (int i=0; i < 3; i++) { + class_minbbox[i] = MAX_BOUNDS; + class_maxbbox[i] = -MAX_BOUNDS; + } +} + void Map::make_brushface(Plane *face) { using math::Vector3f; @@ -445,7 +453,7 @@ void Map::make_brushface(Plane *face) // default material is none unsigned int material = 0; - // default color makrs unknown textures hot pink + // default color makes unknown textures hot pink math::Color color(1.0f, 0.0, 1.0f, 1.0f); // translate texture names to color and material @@ -516,9 +524,7 @@ void Map::make_brushface(Plane *face) // calculate bounding box for (std::vector::iterator it = vl.begin(); it != vl.end(); it++) { - *(*it) *= SCALE; - for (int i=0; i < 3; i++) { if (class_maxbbox[i] < (*(*it))[i]) class_maxbbox[i] = (*(*it))[i]; @@ -528,6 +534,7 @@ void Map::make_brushface(Plane *face) } } + // split polygon into quads while (vl.size() > 3) { std::vector::iterator v0 = vl.begin(); std::vector::reverse_iterator vn = vl.rbegin(); @@ -677,24 +684,28 @@ void Map::load_worldspawn(Model *model) return; // FIXME center in maps without brushes - map_center = (class_minbbox + class_maxbbox) / 2; + map_center = (class_minbbox + class_maxbbox) / 2.0f; model->model_minbbox = class_minbbox - map_center; model->model_maxbbox = class_maxbbox - map_center; model->model_radius = model->model_maxbbox.length(); - load_fragmentgroup(model, model->worldspawn()); + load_fragmentgroup(model, FragmentGroup::None); } -void Map::load_fragmentgroup(Model *model, FragmentGroup &group) +void Map::load_fragmentgroup(Model *model, const FragmentGroup::Type type) { if (!VertexArray::instance() || VertexArray::instance()->overflow()) return; if (!map_materials.size()) return; - + + FragmentGroup *group = new FragmentGroup(); + group->set_type(type); + group->set_location((class_minbbox + class_maxbbox) / 2.0f - map_center); + for (Materials::iterator mit = map_materials.begin(); mit != map_materials.end(); mit++) { // split the Primitives with this material into fragments Primitives *primitives = (*mit).second; @@ -731,8 +742,8 @@ void Map::load_fragmentgroup(Model *model, FragmentGroup &group) } } - // add the fragment to the fragment group - group.push_back(fragment); + // add the fragment to the group + group->push_back(fragment); } // store quads @@ -769,12 +780,14 @@ void Map::load_fragmentgroup(Model *model, FragmentGroup &group) } } - // add the fragment to the model - group.push_back(fragment); + // add the fragment to the group + group->push_back(fragment); } } - + + // add the group to the model + model->add_group(group); } Model * Map::load(std::string const &name) @@ -787,6 +800,7 @@ Model * Map::load(std::string const &name) } Model *model = new Model(name); + mapfile.clear_bbox(); Dock *dock = 0; Particles *particles = 0; @@ -799,13 +813,12 @@ Model * Map::load(std::string const &name) while (mapfile.getline()) { if (mapfile.got_classname("worldspawn")) { - // new wordspawn - - } else if (mapfile.got_classend("worldspawn")) { + mapfile.clear_bbox(); + } else if (mapfile.got_classend("worldspawn")) { mapfile.load_worldspawn(model); mapfile.clear_materials(); - + } else if (mapfile.classname().compare("worldspawn") == 0) { // worldspawn attributes @@ -827,14 +840,28 @@ Model * Map::load(std::string const &name) con_warn "Unknown key " << mapfile.classname() << ":" << mapfile.key() << std::endl; } + } else if (mapfile.got_classname("func_door")) { + mapfile.clear_bbox(); + + } else if (mapfile.got_classend("func_door")) { + mapfile.load_fragmentgroup(model, FragmentGroup::Door); + mapfile.clear_materials(); + + } else if (mapfile.got_classname("func_group")) { + mapfile.clear_bbox(); } else if (mapfile.got_classend("func_group")) { + mapfile.load_fragmentgroup(model, FragmentGroup::None); + mapfile.clear_materials(); - // func_group fragments are loaded into worldspawn - mapfile.load_fragmentgroup(model, model->worldspawn()); + } else if (mapfile.got_classname("func_rotate")) { + mapfile.clear_bbox(); - } else if (mapfile.got_classend()) { + } else if (mapfile.got_classend("func_rotate")) { + mapfile.load_fragmentgroup(model, FragmentGroup::Rotate); + mapfile.clear_materials(); + } else if (mapfile.got_classend()) { mapfile.clear_materials(); } else if (mapfile.got_classname("light")) { diff --git a/src/model/map.h b/src/model/map.h index 5137e6c..9b75f7a 100644 --- a/src/model/map.h +++ b/src/model/map.h @@ -130,10 +130,13 @@ private: void load_worldspawn(Model *model); /// load parsed primitives into a FragmentGroup - void load_fragmentgroup(Model *model, FragmentGroup &group); + void load_fragmentgroup(Model *model, const FragmentGroup::Type type); /// clear the current list of per-material geometry void clear_materials(); + + /// clear class bounding box + void clear_bbox(); /// list of planes for the current brush std::vector planes; diff --git a/src/model/model.cc b/src/model/model.cc index 8fadb33..3ec75d7 100644 --- a/src/model/model.cc +++ b/src/model/model.cc @@ -32,13 +32,17 @@ Model::Model(std::string const & name) : Model::~Model() { - // delete worldspawn - model_worldspawn.clear(); + // delete all fragment groups + for (Groups::iterator git = model_groups.begin(); git != model_groups.end(); git++) { + delete (*git); + } + model_groups.clear(); // delete all docks for (Docks::iterator dit = model_docks.begin(); dit != model_docks.end(); dit++) { delete (*dit); } + model_docks.clear(); // delete all particle systems for (Model::ParticleSystems::iterator pit = model_particles.begin(); pit != model_particles.end(); pit++) { @@ -64,6 +68,11 @@ void Model::add_particles(Particles *particles) model_particles.push_back(particles); } +void Model::add_group(FragmentGroup *group) +{ + model_groups.push_back(group); +} + void Model::add_light(Light *light) { model_lights.push_back(light); @@ -116,7 +125,12 @@ void Model::clear() void Model::list_model(Model *model) { - con_print << " " << model->name() << " " << model->worldspawn().size() << " frags " << + size_t frags = 0; + for (Groups::iterator git = model->groups().begin(); git != model->groups().end(); git++) { + frags += (*git)->size(); + } + + con_print << " " << model->name() << " " << frags << " frags " << model->model_tris_count << "/" << model->model_tris_detail_count << " tris/detail " << model->model_quad_count << "/" << model->model_quad_detail_count << " quads/detail" << std::endl; } diff --git a/src/model/model.h b/src/model/model.h index 5b52fde..bdaa74a 100644 --- a/src/model/model.h +++ b/src/model/model.h @@ -44,6 +44,9 @@ public: /// type definition for a list of model particles typedef std::list ParticleSystems; + + /// type definition for a list of FragmentGroups + typedef std::list Groups; /// create a model with a name Model(std::string const & name); @@ -63,10 +66,10 @@ public: return model_radius; } - /// the worldspawn fragment group - inline FragmentGroup & worldspawn() + /// additional model fragment groups + inline Groups & groups() { - return model_worldspawn; + return model_groups; } /// list of lights @@ -131,6 +134,9 @@ public: /// add a docking location to the model void add_dock(Dock *dock); + + /// add a fragment group to the model + void add_group(FragmentGroup *group); float model_radius; @@ -179,12 +185,11 @@ private: std::string model_name; - FragmentGroup model_worldspawn; - Docks model_docks; Flares model_flares; Lights model_lights; ParticleSystems model_particles; + Groups model_groups; }; } diff --git a/src/render/draw.cc b/src/render/draw.cc index 35b9956..2566dd0 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -575,72 +575,89 @@ void draw_model_fragments(core::Entity *entity) } } - for (model::FragmentGroup::iterator fit = model->worldspawn().begin(); fit != model->worldspawn().end(); fit++) { + for (model::Model::Groups::iterator git = model->groups().begin(); git != model->groups().end(); git++) { - Fragment *fragment = (*fit); + model::FragmentGroup *group = (*git); - if (fragment->material() != material) { - material = fragment->material(); - - if (material & Material::Engine) { - - if (use_color_array) { - glDisableClientState(GL_COLOR_ARRAY); - use_color_array = false; - } - - gl::color(model->enginecolor() * thrust); - - } else if (material & Material::Tertiary) { - if (use_color_array) { - use_color_array = false; - glDisableClientState(GL_COLOR_ARRAY); - } - - math::Color color; - - if ((material & Material::Tertiary) == Material::Tertiary) { - for (size_t i = 0; i < 3; i++) - color[i] = (entity->color()[i] + entity->color_second()[i]) / 2; - - } else if ((material & Material::Secondary) == Material::Secondary) { - color.assign(entity->color_second()); - - } if ((material & Material::Primary) == Material::Primary) { - color.assign(entity->color()); - } - - if (material & Material::Dark) - color *= 0.5f; - - gl::color(color); - - } else { - if (!use_color_array) { - glEnableClientState(GL_COLOR_ARRAY); - use_color_array = true; - } - } + if (group->type() == model::FragmentGroup::Rotate) { + gl::push(); + gl::translate(group->location() * -1.0f); + float angle = math::degrees360f(core::application()->time() * 90.0f); + gl::rotate(angle, math::Vector3f::Xaxis()); + gl::translate(group->location()); + } - if (power && (material & Material::Light)) { - if (use_light) { - gl::disable(GL_LIGHTING); - use_light = false; - } - } else if (power && (material & Material::Engine)) { - if (use_light) { - gl::disable(GL_LIGHTING); - use_light = false; + for (model::FragmentGroup::iterator fit = group->begin(); fit != group->end(); fit++) { + + Fragment *fragment = (*fit); + + if (fragment->material() != material) { + material = fragment->material(); + + if (material & Material::Engine) { + + if (use_color_array) { + glDisableClientState(GL_COLOR_ARRAY); + use_color_array = false; + } + + gl::color(model->enginecolor() * thrust); + + } else if (material & Material::Tertiary) { + if (use_color_array) { + use_color_array = false; + glDisableClientState(GL_COLOR_ARRAY); + } + + math::Color color; + + if ((material & Material::Tertiary) == Material::Tertiary) { + for (size_t i = 0; i < 3; i++) + color[i] = (entity->color()[i] + entity->color_second()[i]) / 2; + + } else if ((material & Material::Secondary) == Material::Secondary) { + color.assign(entity->color_second()); + + } if ((material & Material::Primary) == Material::Primary) { + color.assign(entity->color()); + } + + if (material & Material::Dark) + color *= 0.5f; + + gl::color(color); + + } else { + if (!use_color_array) { + glEnableClientState(GL_COLOR_ARRAY); + use_color_array = true; + } } - } else { - if (!use_light) { - gl::enable(GL_LIGHTING); - use_light = true; + + if (power && (material & Material::Light)) { + if (use_light) { + gl::disable(GL_LIGHTING); + use_light = false; + } + } else if (power && (material & Material::Engine)) { + if (use_light) { + gl::disable(GL_LIGHTING); + use_light = false; + } + } else { + if (!use_light) { + gl::enable(GL_LIGHTING); + use_light = true; + } } } + + draw_fragment(fragment, ext_render(entity)->detailvisible()); } - draw_fragment(fragment, ext_render(entity)->detailvisible()); + if (group->type() == model::FragmentGroup::Rotate) { + gl::pop(); + } } if (!use_light) { -- cgit v1.2.3