/* 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 */ #include "model/engine.h" #include "model/light.h" #include "model/map.h" #include "model/mapfile.h" #include "model/vertexarray.h" #include "sys/sys.h" namespace model { // function to test spawnflags inline bool spawnflag_isset(unsigned int spawnflags, unsigned int flag) { return ((spawnflags & flag) == flag); } Model * Map::load(std::string const &name) { // open the .map file MapFile mapfile; if (!mapfile.open(name)) { return 0; } Model *model = new Model(name); Light *light = 0; Flare *flare = 0; Engine *engine = 0; unsigned int u; while (mapfile.getline()) { if (mapfile.got_classname("worldspawn")) { // new wordspawn } else if (mapfile.classname().compare("worldspawn") == 0 ) { // worldspawn attributes if (mapfile.got_key_int("enginesound", u)) { model->model_enginesound = u; continue; } } else if (mapfile.got_classname("light")) { // new light light = new Light(); model->add_light(light); } else if (mapfile.classname().compare("light") == 0 ) { // light attributes if (mapfile.got_key_vector3f("origin", light->light_location)) { light->light_location *= SCALE; continue; } else if (mapfile.got_key_color("_color", light->light_color)) { continue; } else if (mapfile.got_key_int("spawnflags", u)) { light->light_strobe = spawnflag_isset(u, 1); light->light_entity = spawnflag_isset(u, 2); } else if (mapfile.got_key_float("light", light->light_radius)) { light->light_radius /= 100.0f; } else if (mapfile.got_key_float("frequency", light->light_frequency)) { continue; } else if (mapfile.got_key_float("offset", light->light_offset)) { continue; } else if (mapfile.got_key_float("time", light->light_time)) { continue; } else if (mapfile.got_key_int("flare", light->light_flare)) { continue; } } else if (mapfile.got_classname("target_flare")) { // new flare flare = new Flare(); model->add_flare(flare); } else if (mapfile.classname().compare("target_flare") == 0 ) { // flare attributes if (mapfile.got_key_vector3f("origin", flare->light_location)) { flare->light_location *= SCALE; continue; } else if (mapfile.got_key_color("_color", flare->light_color)) { continue; } else if (mapfile.got_key_int("spawnflags", u)) { flare->light_strobe = spawnflag_isset(u, 1); flare->light_entity = spawnflag_isset(u, 2); } else if (mapfile.got_key_float("radius", flare->light_radius)) { flare->light_radius /= 100.0f; } else if (mapfile.got_key_float("frequency", flare->light_frequency)) { continue; } else if (mapfile.got_key_float("offset", flare->light_offset)) { continue; } else if (mapfile.got_key_float("time", flare->light_time)) { continue; } else if (mapfile.got_key_int("flare", flare->light_flare)) { continue; } else if (mapfile.got_key_float("angle", flare->flare_angle)) { flare->flare_angle = math::degrees360f(flare->flare_angle); continue; } } else if (mapfile.got_classname("target_engine")) { // new engine engine = new Engine(); model->add_engine(engine); } else if (mapfile.classname().compare("target_engine") == 0 ) { // engine attributes if (mapfile.got_key_vector3f("origin", engine->engine_location)) { engine->engine_location *= SCALE; continue; } else if (mapfile.got_key_color("_color", engine->engine_color)) { continue; } else if (mapfile.got_key_float("radius", engine->engine_radius)) { engine->engine_radius /= 100.0f; continue; } else if (mapfile.got_key_int("flare", engine->engine_flare)) { continue; } else if (mapfile.got_key_color("_color", engine->engine_color)) { continue; } } } mapfile.close(); // process the triangles calculated by the mapfile and add them to the vertex array if (VertexArray::instance() && !VertexArray::instance()->overflow() && ((mapfile.class_tris.size() + mapfile.class_etris.size() + mapfile.class_ltris.size()) > 0)) { math::Vector3f center = (mapfile.class_minbbox + mapfile.class_maxbbox) / 2; model->model_minbbox = mapfile.class_minbbox - center; model->model_maxbbox = mapfile.class_maxbbox - center; model->model_radius = model->model_maxbbox.length(); // structural triangles model->model_first_vertex = VertexArray::instance()->index()/3; for (std::list::iterator it = mapfile.class_tris.begin(); it != mapfile.class_tris.end() && !VertexArray::instance()->overflow(); it++) { Triangle *triangle = (*it); if (!triangle->detail()) { size_t count = 0; count += VertexArray::instance()->add_vertex(triangle->triangle_v0-center, triangle->normal(), triangle->color() ); count += VertexArray::instance()->add_vertex(triangle->triangle_v1-center, triangle->normal(), triangle->color() ); count += VertexArray::instance()->add_vertex(triangle->triangle_v2-center, triangle->normal(), triangle->color() ); if (count == 3) model->model_vertex_count += count; } } // detail triangles for (std::list::iterator it = mapfile.class_tris.begin(); it != mapfile.class_tris.end() && !VertexArray::instance()->overflow(); it++) { Triangle *triangle = (*it); if (triangle->detail()) { size_t count = 0; count += VertexArray::instance()->add_vertex(triangle->triangle_v0-center, triangle->normal(), triangle->color() ); count += VertexArray::instance()->add_vertex(triangle->triangle_v1-center, triangle->normal(), triangle->color() ); count += VertexArray::instance()->add_vertex(triangle->triangle_v2-center, triangle->normal(), triangle->color() ); if (count == 3) model->model_vertex_countdetail += count; } delete triangle; } mapfile.class_tris.clear(); // structural etriangles model->model_first_evertex = VertexArray::instance()->index()/3; for (std::list::iterator it = mapfile.class_etris.begin(); it != mapfile.class_etris.end() && !VertexArray::instance()->overflow(); it++) { Triangle *triangle = (*it); if (!triangle->detail()) { size_t count = 0; count += VertexArray::instance()->add_vertex(triangle->triangle_v0-center, triangle->normal(), triangle->color() ); count += VertexArray::instance()->add_vertex(triangle->triangle_v1-center, triangle->normal(), triangle->color() ); count += VertexArray::instance()->add_vertex(triangle->triangle_v2-center, triangle->normal(), triangle->color() ); if (count == 3) model->model_evertex_count += count; } } // detail etriangles for (std::list::iterator it = mapfile.class_etris.begin(); it != mapfile.class_etris.end() && !VertexArray::instance()->overflow(); it++) { Triangle *triangle = (*it); if (triangle->detail()) { size_t count = 0; count += VertexArray::instance()->add_vertex(triangle->triangle_v0-center, triangle->normal(), triangle->color() ); count += VertexArray::instance()->add_vertex(triangle->triangle_v1-center, triangle->normal(), triangle->color() ); count += VertexArray::instance()->add_vertex(triangle->triangle_v2-center, triangle->normal(), triangle->color() ); if (count == 3) model->model_evertex_countdetail += count; } delete triangle; } mapfile.class_etris.clear(); // structural ltriangles model->model_first_lvertex = VertexArray::instance()->index()/3; for (std::list::iterator it = mapfile.class_ltris.begin(); it != mapfile.class_ltris.end() && !VertexArray::instance()->overflow(); it++) { Triangle *triangle = (*it); if (!triangle->detail()) { size_t count = 0; count += VertexArray::instance()->add_vertex(triangle->triangle_v0-center, triangle->normal(), triangle->color() ); count += VertexArray::instance()->add_vertex(triangle->triangle_v1-center, triangle->normal(), triangle->color() ); count += VertexArray::instance()->add_vertex(triangle->triangle_v2-center, triangle->normal(), triangle->color() ); if (count == 3) model->model_lvertex_count += count; } } // detail ltriangles for (std::list::iterator it = mapfile.class_ltris.begin(); it != mapfile.class_ltris.end() && !VertexArray::instance()->overflow(); it++) { Triangle *triangle = (*it); if (triangle->detail()) { size_t count = 0; count += VertexArray::instance()->add_vertex(triangle->triangle_v0-center, triangle->normal(), triangle->color() ); count += VertexArray::instance()->add_vertex(triangle->triangle_v1-center, triangle->normal(), triangle->color() ); count += VertexArray::instance()->add_vertex(triangle->triangle_v2-center, triangle->normal(), triangle->color() ); if (count == 3) model->model_lvertex_countdetail += count; } delete triangle; } mapfile.class_ltris.clear(); // reposition light and engines for (std::list::iterator eit = model->model_engine.begin(); eit != model->model_engine.end(); eit++) { (*eit)->engine_location -= center; } for (std::list::iterator lit = model->model_light.begin(); lit != model->model_light.end(); lit++) { (*lit)->light_location -= center; } for (std::list::iterator flit = model->model_flare.begin(); flit != model->model_flare.end(); flit++) { (*flit)->light_location -= center; } } con_print << " maps/" << model->name() << ".map " << mapfile.brushes << " brushes " << model->tris() << " tris (" << model->details() << " detail)" << std::endl; return model; } }