diff options
-rw-r--r-- | osirion.kdevelop | 18 | ||||
-rw-r--r-- | src/math/color.cc | 9 | ||||
-rw-r--r-- | src/math/color.h | 3 | ||||
-rw-r--r-- | src/model/Makefile.am | 2 | ||||
-rw-r--r-- | src/model/engine.cc | 5 | ||||
-rw-r--r-- | src/model/engine.h | 40 | ||||
-rw-r--r-- | src/model/flare.cc | 9 | ||||
-rw-r--r-- | src/model/flare.h | 15 | ||||
-rw-r--r-- | src/model/fragment.cc | 17 | ||||
-rw-r--r-- | src/model/fragment.h | 44 | ||||
-rw-r--r-- | src/model/light.cc | 9 | ||||
-rw-r--r-- | src/model/light.h | 77 | ||||
-rw-r--r-- | src/model/map.cc | 705 | ||||
-rw-r--r-- | src/model/map.h | 112 | ||||
-rw-r--r-- | src/model/model.cc | 103 | ||||
-rw-r--r-- | src/model/model.h | 179 | ||||
-rw-r--r-- | src/model/plane.cc | 16 | ||||
-rw-r--r-- | src/model/plane.h | 55 | ||||
-rw-r--r-- | src/model/primitives.cc | 44 | ||||
-rw-r--r-- | src/model/primitives.h | 45 | ||||
-rw-r--r-- | src/model/quad.cc | 17 | ||||
-rw-r--r-- | src/model/quad.h | 57 | ||||
-rw-r--r-- | src/model/triangle.cc | 17 | ||||
-rw-r--r-- | src/model/triangle.h | 52 | ||||
-rw-r--r-- | src/model/vertexarray.cc | 55 | ||||
-rw-r--r-- | src/model/vertexarray.h | 67 | ||||
-rw-r--r-- | src/render/draw.cc | 175 |
27 files changed, 1132 insertions, 815 deletions
diff --git a/osirion.kdevelop b/osirion.kdevelop index c31777e..c65b0a6 100644 --- a/osirion.kdevelop +++ b/osirion.kdevelop @@ -16,12 +16,12 @@ <projectdirectory>./</projectdirectory> <absoluteprojectpath>false</absoluteprojectpath> <description>The OSiRiON Project is an SDL+OpenGL space game.</description> - <defaultencoding></defaultencoding> + <defaultencoding/> <versioncontrol>kdevsubversion</versioncontrol> </general> <kdevautoproject> <general> - <activetarget>src/client/libclient.la</activetarget> + <activetarget>src/model/libmodel.la</activetarget> <useconfiguration>debug</useconfiguration> </general> <run> @@ -140,7 +140,7 @@ <projectdoc> <docsystem>Doxygen documentatieverzameling</docsystem> <docurl>osirion.tag</docurl> - <usermanualurl></usermanualurl> + <usermanualurl/> </projectdoc> </kdevdocumentation> <substmap> @@ -196,7 +196,7 @@ <designerpluginpaths/> </qt> <creategettersetter> - <prefixGet></prefixGet> + <prefixGet/> <prefixSet>set</prefixSet> <prefixVariable>m_,_</prefixVariable> <parameterName>theValue</parameterName> @@ -228,11 +228,11 @@ </cppsupportpart> <kdevdebugger> <general> - <gdbpath></gdbpath> - <dbgshell></dbgshell> - <configGdbScript></configGdbScript> - <runShellScript></runShellScript> - <runGdbScript></runGdbScript> + <gdbpath/> + <dbgshell/> + <configGdbScript/> + <runShellScript/> + <runGdbScript/> <breakonloadinglibs>true</breakonloadinglibs> <separatetty>false</separatetty> <floatingtoolbar>false</floatingtoolbar> diff --git a/src/math/color.cc b/src/math/color.cc index 1e52ec5..0cf2ea8 100644 --- a/src/math/color.cc +++ b/src/math/color.cc @@ -123,6 +123,15 @@ Color const operator*(float scalar, Color const & color) { return color * scalar; } + +Color & Color::operator*=(const float scalar) +{ + for (int i=0; i < 3; i++) + rgba_data[i] *= scalar; + return (*this); +} + + std::ostream &operator<<(std::ostream &os, Color const & color) { os << color.red() << " " << color.green() << " " << color.blue(); // << " " << c.alpha(); diff --git a/src/math/color.h b/src/math/color.h index ea6fe1c..4f3df16 100644 --- a/src/math/color.h +++ b/src/math/color.h @@ -46,6 +46,9 @@ public: /// multiply rgb values with scalar value. Color operator*(const float scalar) const; + /// multiply rgb values with scalar value. + Color & operator*=(const float scalar); + inline float operator[](size_t index) const { return rgba_data[index]; } /// pointer to the internal data diff --git a/src/model/Makefile.am b/src/model/Makefile.am index 4a5e4e6..a6e8a99 100644 --- a/src/model/Makefile.am +++ b/src/model/Makefile.am @@ -1,7 +1,7 @@ METASOURCES = AUTO libmodel_la_SOURCES = engine.cc flare.cc fragment.cc light.cc map.cc model.cc \ - plane.cc quad.cc triangle.cc vertexarray.cc + plane.cc primitives.cc quad.cc triangle.cc vertexarray.cc libmodel_la_LDFLAGS = -avoid-version -no-undefined -lm noinst_LTLIBRARIES = libmodel.la diff --git a/src/model/engine.cc b/src/model/engine.cc index 7c8d117..eb4198a 100644 --- a/src/model/engine.cc +++ b/src/model/engine.cc @@ -7,13 +7,14 @@ #include "model/engine.h" -namespace model { +namespace model +{ /* ---------- core::Engine ------------------------------------------ */ Engine::Engine() : - engine_location() + engine_location() { engine_radius = 1.0f; engine_flare = 0; diff --git a/src/model/engine.h b/src/model/engine.h index 569eb4e..c3e6064 100644 --- a/src/model/engine.h +++ b/src/model/engine.h @@ -10,32 +10,48 @@ #include "math/vector3f.h" #include "math/color.h" -namespace model { +namespace model +{ /// a spacecraft engine class Engine { public: Engine(); - + Engine(math::Vector3f const & location); ~Engine(); - inline math::Vector3f const & location() const { return engine_location; } - - inline math::Color const & color() const { return engine_color; } - - inline float radius() const { return engine_radius; } - - inline unsigned int flare() const { return engine_flare; } - - inline unsigned int texture() const { return render_texture; } + inline math::Vector3f const & location() const + { + return engine_location; + } + + inline math::Color const & color() const + { + return engine_color; + } + + inline float radius() const + { + return engine_radius; + } + + inline unsigned int flare() const + { + return engine_flare; + } + + inline unsigned int texture() const + { + return render_texture; + } math::Vector3f engine_location; float engine_radius; math::Color engine_color; unsigned int engine_flare; - + unsigned int render_texture; }; diff --git a/src/model/flare.cc b/src/model/flare.cc index fcd36f1..0669a49 100644 --- a/src/model/flare.cc +++ b/src/model/flare.cc @@ -6,14 +6,15 @@ #include "model/flare.h" -namespace model { +namespace model +{ -Flare::Flare() : Light() { +Flare::Flare() : Light() +{ flare_angle = 0; } Flare::~Flare() -{ -} +{} } diff --git a/src/model/flare.h b/src/model/flare.h index 3cd192c..6f96d8c 100644 --- a/src/model/flare.h +++ b/src/model/flare.h @@ -9,16 +9,21 @@ #include "model/light.h" -namespace model { +namespace model +{ /// a flare is a directional light -class Flare : public Light { +class Flare : public Light +{ public: Flare(); ~Flare(); - - inline float angle() const { return flare_angle; } - + + inline float angle() const + { + return flare_angle; + } + float flare_angle; }; diff --git a/src/model/fragment.cc b/src/model/fragment.cc index 38990d5..b655807 100644 --- a/src/model/fragment.cc +++ b/src/model/fragment.cc @@ -10,10 +10,14 @@ namespace model { +/* + Triangles: the number of triangles is size/3 + Quads: the number of Quads is size/4 +*/ Fragment::Fragment(Type type, unsigned int material) { fragment_type = type; - fragment_start = VertexArray::instance()->index(); + fragment_index = VertexArray::instance()->index() / 3; fragment_material = material; fragment_structural_size = 0; fragment_detail_size = 0; @@ -22,11 +26,12 @@ Fragment::Fragment(Type type, unsigned int material) size_t Fragment::add_vertex(math::Vector3f const & vertex, math::Vector3f const &normal, math::Color const & color, bool detail) { size_t n = VertexArray::instance()->add_vertex(vertex, normal, color); - - if (detail) - fragment_detail_size += n; - else - fragment_structural_size += n; + if (n) { + if (detail) + fragment_detail_size += n; + else + fragment_structural_size += n; + } return n; } diff --git a/src/model/fragment.h b/src/model/fragment.h index ba4eaf9..0df1b79 100644 --- a/src/model/fragment.h +++ b/src/model/fragment.h @@ -19,28 +19,46 @@ class Fragment public: /// fragment primitive type: triangles or quads enum Type {Triangles, Quads}; - + /// create a new fragment - Fragment (Type type, unsigned int material); - + Fragment(Type type, unsigned int material); + /// add a vertex to the fragment size_t add_vertex(math::Vector3f const & vertex, math::Vector3f const &normal, math::Color const & color, bool detail); - + + /// the type of primitives this fragment consists of + inline Type type() const + { + return fragment_type; + } + /// VertexArray index of the start of the fragment - inline size_t start() const { return fragment_start; } - + inline size_t index() const + { + return fragment_index; + } + /// number of structural vertices in the fragment - inline size_t structural_size() const { return fragment_structural_size; } - + inline size_t structural_size() const + { + return fragment_structural_size; + } + /// number of detail vertices in the fragment - inline size_t detail_size() const { return fragment_detail_size; } - + inline size_t detail_size() const + { + return fragment_detail_size; + } + /// material flags - inline unsigned int material() { return fragment_material; } - + inline unsigned int material() + { + return fragment_material; + } + private: Type fragment_type; - size_t fragment_start; + size_t fragment_index; size_t fragment_structural_size; size_t fragment_detail_size; unsigned int fragment_material; diff --git a/src/model/light.cc b/src/model/light.cc index 426e7fd..01ddf96 100644 --- a/src/model/light.cc +++ b/src/model/light.cc @@ -6,11 +6,12 @@ #include "model/light.h" -namespace model { +namespace model +{ -Light::Light() : - light_location(), - light_color(1.0f, 1.0f, 1.0f) +Light::Light() : + light_location(), + light_color(1.0f, 1.0f, 1.0f) { light_entity = false; light_strobe = false; diff --git a/src/model/light.h b/src/model/light.h index b834623..00587f3 100644 --- a/src/model/light.h +++ b/src/model/light.h @@ -10,45 +10,76 @@ #include "math/vector3f.h" #include "math/color.h" -namespace model { +namespace model +{ /// an exterior light class Light { public: Light(); - + Light(math::Vector3f const & location, math::Color const & color, bool strobe=false); - + ~Light(); - inline math::Vector3f const & location() const { return light_location; } - - inline math::Color const & color() const { return light_color; }; - + inline math::Vector3f const & location() const + { + return light_location; + } + + inline math::Color const & color() const + { + return light_color; + }; + /// true if this is a strobe light - inline bool strobe() const { return light_strobe; } - + inline bool strobe() const + { + return light_strobe; + } + /// true if this light has entity color - inline bool entity() const { return light_entity; } - + inline bool entity() const + { + return light_entity; + } + /// size if the light, default is 1.0f - inline float radius() const { return light_radius; } + inline float radius() const + { + return light_radius; + } /// strobe time offset, in seconds - inline float offset() const { return light_offset; } - + inline float offset() const + { + return light_offset; + } + /// frequency in strobes per second - inline float frequency() const { return light_frequency; } - + inline float frequency() const + { + return light_frequency; + } + /// fraction a strobe light will be on, default is 0.5f - inline float time() const { return light_time; } - + inline float time() const + { + return light_time; + } + /// flare texture number - inline unsigned int flare() const { return light_flare; } - + inline unsigned int flare() const + { + return light_flare; + } + /// render texture number - inline size_t texture() const { return render_texture; } + inline size_t texture() const + { + return render_texture; + } math::Vector3f light_location; math::Color light_color; @@ -58,9 +89,9 @@ public: float light_frequency; float light_offset; float light_time; - + unsigned int light_flare; - + size_t render_texture; }; diff --git a/src/model/map.cc b/src/model/map.cc index 220c723..8260f10 100644 --- a/src/model/map.cc +++ b/src/model/map.cc @@ -10,170 +10,55 @@ #include "model/light.h" #include "model/map.h" #include "model/material.h" +#include "model/model.h" #include "model/vertexarray.h" #include "sys/sys.h" #include <sstream> #include <string> -namespace model { +namespace model +{ // function to test spawnflags -inline bool spawnflag_isset(unsigned int spawnflags, unsigned int flag) { +inline bool spawnflag_isset(unsigned int spawnflags, unsigned int flag) +{ return ((spawnflags & flag) == flag); } +// max geometry bounds const float MAX_BOUNDS = 16384; -const float MIN_DELTA = 10e-10; - -Model * Map::load(std::string const &name) -{ - // open the .map file - Map 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; +// scaling factor when loading .map geometry +const float SCALE = 1.0f / 1024.0f; - } 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; +const float MIN_DELTA = 10e-10; - } else if (mapfile.got_key_float("radius", engine->engine_radius)) { - engine->engine_radius /= 100.0f; - continue; +Map::Map() +{ + mapfile_name.clear(); +} - } else if (mapfile.got_key_int("flare", engine->engine_flare)) { - continue; +Map::~Map() +{ + clear_materials(); +} - } else if (mapfile.got_key_color("_color", engine->engine_color)) { - continue; - } - } +void Map::clear_materials() +{ + for (Materials::iterator mit = map_materials.begin(); mit != map_materials.end(); mit++) { + // delete list of primitives + delete(*mit).second; } - - mapfile.close(); - - mapfile.load_fragments(model); - - return model; + map_materials.clear(); + + map_brushes = 0; + map_faces = 0; + map_faces_detail = 0; } -Map::Map() {} - -Map::~Map() {} - -bool Map::open(std::string const & name) { +bool Map::open(std::string const & name) +{ last_read_was_classname = false; last_read_was_key = false; @@ -182,13 +67,14 @@ bool Map::open(std::string const & name) { classname_current = ""; line_number = 0; parse_level = 0; - brushes = 0; - + + clear_materials(); + mapfile_name.assign("maps/"); mapfile_name.append(name); mapfile_name.append(".map"); - filesystem::File *f = filesystem::open(mapfile_name.c_str()); + filesystem::File *f = filesystem::open(mapfile_name.c_str()); if (!f) { con_warn << "Could not open " << mapfile_name << std::endl; return false; @@ -203,33 +89,36 @@ bool Map::open(std::string const & name) { con_warn << "Could not stream " << fn << "!\n"; return false; } - + return true; } -bool Map::got_classname() const { +bool Map::got_classname() const +{ return last_read_was_classname; } -bool Map::got_classname(const char * classnamelabel) const { +bool Map::got_classname(const char * classnamelabel) const +{ return (last_read_was_classname && (classname_current.compare(classnamelabel) == 0)); } -bool Map::getline() { +bool Map::getline() +{ using math::Vector3f; - + char data[1024]; - + last_read_was_classname = false; last_read_was_key = false; - + key_current = ""; value_current = ""; - + if (!mapfile_ifs.is_open()) return false; - + if (mapfile_ifs.getline(data, 1023)) { line_number++; std::istringstream linestream(data); @@ -238,13 +127,13 @@ bool Map::getline() { if (linestream >> firstword) { if (!firstword.size()) { return true; - + } else if (firstword == "//") { return true; - + } else if (firstword == "{") { parse_level++; - + } else if (firstword == "}") { if ((parse_level == 2) && (classname_current == "worldspawn")) { // brush @@ -253,24 +142,24 @@ bool Map::getline() { for (std::vector<Plane *>::iterator face = planes.begin(); face != planes.end(); face++) { make_brushface((*face)); } - + // clean planes for (std::vector<Plane *>::iterator it = planes.begin(); it != planes.end(); it++) { delete(*it); } planes.clear(); - - brushes++; + + map_brushes++; } value_current.clear(); } parse_level--; - + } else if (parse_level == 1) { - + if (firstword == "\"classname\"") { classname_current.clear(); - + if (linestream >> classname_current) { if (classname_current.size() > 2) { classname_current.erase(0,1); @@ -280,24 +169,24 @@ bool Map::getline() { classname_current.clear(); } } - + } else if ((firstword.size() > 2) && (firstword[0] == '\"') && (firstword[firstword.size()-1] == '\"')) { - + key_current.assign(firstword); key_current.erase(0,1); key_current.erase(key_current.size()-1, 1); - + value_current.clear(); char c; while ((linestream.get(c)) && (c != '"')); while ((linestream.get(c)) && (c != '"')) value_current += c; - + last_read_was_key = true; } } else if (parse_level == 2) { - + if ((firstword == "(") && (classname_current == "worldspawn")) { // brush plane if (VertexArray::instance()) { @@ -319,21 +208,21 @@ bool Map::getline() { // 5 numbers (texture alignment?) for (int i=0; i < 5; i++) linestream >> tmp; - + // content flags ? if (!(linestream >> n)) n = 0; - + Plane *plane = new Plane(p1, p2, p3); plane->texture() = texture; if (n > 0) plane->detail() = true; - + // surface flags if (!(linestream >> n)) n = 0; plane->surface_flags() = n; - + planes.push_back(plane); } value_current.clear(); @@ -341,10 +230,10 @@ bool Map::getline() { } } } else { - + return false; } - + return true; } @@ -361,7 +250,13 @@ void Map::make_brushface(Plane *face) if (face->texture() == "common/clip") { return; } - + + // statistics + map_faces++; + if (face->detail()) { + map_faces_detail++; + } + // using suggestions from // http://www.flipcode.com/archives/Level_Editing.shtml @@ -372,7 +267,7 @@ void Map::make_brushface(Plane *face) // check if the face is x-axis oriented if ((fabsf(face->normal().x) >= fabsf(face->normal().y)) && (fabsf(face->normal().x) >= fabsf(face->normal().z))) { - + if (face->normal().x >= 0) { vl.push_back(new math::Vector3f(0, -MAX_BOUNDS, -MAX_BOUNDS)); vl.push_back(new math::Vector3f(0, -MAX_BOUNDS, MAX_BOUNDS)); @@ -395,7 +290,7 @@ void Map::make_brushface(Plane *face) // check if the face is y-axis oriented else if ((fabsf(face->normal().y) >= fabsf(face->normal().x)) && (fabsf(face->normal().y) >= fabsf(face->normal().z))) { - + if (face->normal().y >= 0) { vl.push_back(new Vector3f(MAX_BOUNDS, 0, -MAX_BOUNDS)); vl.push_back(new Vector3f(MAX_BOUNDS, 0, MAX_BOUNDS)); @@ -419,7 +314,7 @@ void Map::make_brushface(Plane *face) // face must be z-axis oriented else { - + if (face->normal().z >= 0) { vl.push_back(new Vector3f(-MAX_BOUNDS, -MAX_BOUNDS, 0)); vl.push_back(new Vector3f(-MAX_BOUNDS, MAX_BOUNDS, 0)); @@ -461,7 +356,7 @@ void Map::make_brushface(Plane *face) for (int i=0; vl.size() - i > 0; i++) { Vector3f v(*vl.at(i)); - + Vector3f next; if (vl.size() - i > 1) { next = *vl.at(i+1); @@ -492,7 +387,7 @@ void Map::make_brushface(Plane *face) float t2 = (plane->normal().x * v.x - plane->normal().x * prev.x + plane->normal().y * v.y - plane->normal().y * prev.y + plane->normal().z * v.z - plane->normal().z * prev.z); - + Vector3f *s = new Vector3f; if (t2 == 0) { @@ -509,7 +404,7 @@ void Map::make_brushface(Plane *face) // check if next - v intersects with plane if ((next.x*plane->normal().x + next.y*plane->normal().y + next.z*plane->normal().z + plane->d()) > -MIN_DELTA) { - + // calculate intersection float t1 = -plane->normal().x * v.x - plane->normal().y * v.y - plane->normal().z * v.z -plane->d(); float t2 = (plane->normal().x * next.x - plane->normal().x * v.x + @@ -543,72 +438,84 @@ void Map::make_brushface(Plane *face) // default material is none unsigned int material = 0; - + // default color makrs unknown textures hot pink math::Color color(1.0f, 0.0, 1.0f, 1.0f); - + // translate texture names to color and material - if (face->texture() == "colors/white") { + if (face->texture().compare("colors/white") == 0) { color.assign(1.0f); - } else if (face->texture() == "colors/grey90") { + } else if (face->texture().compare("colors/grey90") == 0) { color.assign(0.9f); - } else if (face->texture() == "colors/grey75") { + } else if (face->texture().compare("colors/grey75") == 0) { color.assign(0.75f); - } else if (face->texture() == "colors/grey50") { + } else if (face->texture().compare("colors/grey50") == 0) { color.assign(0.5f); - } else if (face->texture() == "colors/grey25") { + } else if (face->texture().compare("colors/grey25") == 0) { color.assign(0.25f); - } else if (face->texture() == "colors/black") { + } else if (face->texture().compare("colors/black") == 0) { color.assign(0.0f); - } else if (face->texture() == "colors/red") { + } else if (face->texture().compare("colors/red") == 0) { color.assign(1, 0, 0); - } else if (face->texture() == "colors/green") { + } else if (face->texture().compare("colors/green") == 0) { color.assign(0, 1, 0); - } else if (face->texture() == "colors/blue") { + } else if (face->texture().compare("colors/blue") == 0) { color.assign(0, 0, 1); - - } else if ((face->texture() == "common/entity") || (face->texture() == "common/primary")) { + + } else if ((face->texture().compare("common/entity") == 0) || (face->texture().compare("common/primary") == 0)) { material |= Material::Primary; - } else if (face->texture() == "common/primary_dark") { + } else if (face->texture().compare("common/primary_dark") == 0) { material |= Material::Primary; material |= Material::Dark; - - } else if (face->texture() == "common/secundary") { + + } else if (face->texture().compare("common/secundary") == 0) { material |= Material::Secondary; - } else if (face->texture() == "common/secundary_dark") { + } else if (face->texture().compare("common/secundary_dark") == 0) { material |= Material::Secondary; material |= Material::Dark; - - } else if (face->texture() == "common/tertiary") { + + } else if (face->texture().compare("common/tertiary") == 0) { material |= Material::Tertiary; - } else if (face->texture() == "common/tertiary_dark") { + } else if (face->texture().compare("common/tertiary_dark") == 0) { material |= Material::Tertiary; material |= Material::Dark; } - + // translate surface flags to materials - + // surface flag 1 light if ((face->surface_flags() & 1) == 1) { material |= Material::Light; } - + + // find the list if primitives for the current material, allocate a new one if necessary + Primitives *primitives = 0; + + Materials::iterator mit = map_materials.find(material); + if (mit == map_materials.end()) { + primitives = new Primitives(material); + map_materials[material] = primitives; + } else { + primitives = (*mit).second; + } + // calculate bounding box - for (std::vector<Vector3f *>::iterator it = vl.begin(); it != vl.end(); it++) { - + for (std::vector<Vector3f *>::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]; - + if (class_minbbox[i] > (*(*it))[i]) class_minbbox[i] = (*(*it))[i]; } } - + // split face into triangles - while (vl.size() >2 ) { + // FIXME split off quads + while (vl.size() >2) { std::vector<Vector3f *>::iterator v0 = vl.begin(); std::vector<Vector3f *>::reverse_iterator vn = vl.rbegin(); std::vector<Vector3f *>::reverse_iterator vn1 = vl.rbegin(); @@ -616,21 +523,9 @@ void Map::make_brushface(Plane *face) Vector3f n(face->normal()*-1); n.normalize(); - - if (material & Material::Primary) { - // evertices will be added to the VertexArray after normal vertices - Triangle *triangle = new Triangle(*(*vn1), *(*vn), *(*v0), n, 0, face->detail()); - class_etris.push_back(triangle); - } else if (material & Material::Light) { - // lvertices - Triangle *triangle = new Triangle(*(*vn1), *(*vn), *(*v0), n, color, face->detail()); - class_ltris.push_back(triangle); - } else { - Triangle *triangle = new Triangle(*(*vn1), *(*vn), *(*v0), n, color, face->detail()); - class_tris.push_back(triangle); - } - - delete (*vn); + + primitives->add_triangle(*(*vn1), *(*vn), *(*v0), n, color, face->detail()); + delete(*vn); vl.pop_back(); } } else { @@ -645,8 +540,9 @@ void Map::make_brushface(Plane *face) vl.clear(); } -bool Map::got_key_string(const char * keylabel, std::string & valuestring) { - if (last_read_was_key && (key_current.compare(keylabel) == 0 )) { +bool Map::got_key_string(const char * keylabel, std::string & valuestring) +{ + if (last_read_was_key && (key_current.compare(keylabel) == 0)) { valuestring.assign(value_current); return true; } else { @@ -654,14 +550,15 @@ bool Map::got_key_string(const char * keylabel, std::string & valuestring) { } } -bool Map::got_key_vector3f(const char * keylabel, math::Vector3f & v) { - if (last_read_was_key && (key_current.compare(keylabel) == 0 )) { +bool Map::got_key_vector3f(const char * keylabel, math::Vector3f & v) +{ + if (last_read_was_key && (key_current.compare(keylabel) == 0)) { std::istringstream is(value_current); float x, y, z; if ((is >> x) && (is >> y) && (is >> z)) { v = math::Vector3f(x,y,z); } else { - v= math::Vector3f(); + v= math::Vector3f(); } return true; } else { @@ -669,8 +566,9 @@ bool Map::got_key_vector3f(const char * keylabel, math::Vector3f & v) { } } -bool Map::got_key_float(const char * keylabel, float & f) { - if (last_read_was_key && (key_current.compare(keylabel) == 0 )) { +bool Map::got_key_float(const char * keylabel, float & f) +{ + if (last_read_was_key && (key_current.compare(keylabel) == 0)) { std::istringstream is(value_current); if (!(is >> f)) { f = 0; @@ -683,7 +581,7 @@ bool Map::got_key_float(const char * keylabel, float & f) { bool Map::got_key_int(const char * keylabel, unsigned int & u) { - if (last_read_was_key && (key_current.compare(keylabel) == 0 )) { + if (last_read_was_key && (key_current.compare(keylabel) == 0)) { std::istringstream is(value_current); if (!(is >> u)) { u = 0; @@ -694,12 +592,14 @@ bool Map::got_key_int(const char * keylabel, unsigned int & u) } } -bool Map::got_key(const char * keylabel) { - return (last_read_was_key && (key_current.compare(keylabel) == 0 )); +bool Map::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) { - if (last_read_was_key && (key_current.compare(keylabel) == 0 )) { +bool Map::got_key_angle(const char * keylabel, float & f) +{ + if (last_read_was_key && (key_current.compare(keylabel) == 0)) { std::istringstream is(value_current); if ((is >> f)) { f = math::degrees360f(f); @@ -712,13 +612,16 @@ bool Map::got_key_angle(const char * keylabel, float & f) { } } -bool Map::got_key_color(const char * keylabel, math::Color & color) { - if (last_read_was_key && (key_current.compare(keylabel) == 0 )) { +bool Map::got_key_color(const char * keylabel, math::Color & color) +{ + if (last_read_was_key && (key_current.compare(keylabel) == 0)) { std::istringstream is(value_current); float r, g, b; if ((is >> r) && (is >> g) && (is >> b)) { if ((r > 1) || (g > 1) || (b > 1)) { - r /= 255; g /= 255; b /= 255; + r /= 255; + g /= 255; + b /= 255; } color = math::Color(r, g, b); } else { @@ -739,119 +642,231 @@ void Map::load_fragments(Model *model) { if (!VertexArray::instance() || VertexArray::instance()->overflow()) return; - - // process the triangles calculated by the mapfile and add them to the vertex array - if ((class_tris.size() + class_etris.size() + class_ltris.size()) > 0) { - - math::Vector3f center = (class_minbbox + class_maxbbox) / 2; - - model->model_minbbox = class_minbbox - center; - model->model_maxbbox = class_maxbbox - center; - - model->model_radius = model->model_maxbbox.length(); - - // structural triangles - model->model_first_vertex = VertexArray::instance()->index()/3; - for (std::list<Triangle *>::iterator it = class_tris.begin(); it != class_tris.end(); it++) { - Triangle *triangle = (*it); - if (!triangle->detail()) { - size_t count = 0; - count += VertexArray::instance()->add_vertex(triangle->v0()-center, triangle->normal(), triangle->color() ); - count += VertexArray::instance()->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color() ); - count += VertexArray::instance()->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color() ); - if (count == 3) - model->model_vertex_count += count; + + if (!map_materials.size()) + return; + + // FIXME center in maps without brushes + math::Vector3f center = (class_minbbox + class_maxbbox) / 2; + + model->model_minbbox = class_minbbox - center; + model->model_maxbbox = class_maxbbox - center; + + model->model_radius = model->model_maxbbox.length(); + + // reposition lights, flares and engines + for (Model::Lights::iterator lit = model->lights().begin(); lit != model->lights().end(); lit++) { + (*lit)->light_location -= center; + } + + for (Model::Flares::iterator flit = model->flares().begin(); flit != model->flares().end(); flit++) { + (*flit)->light_location -= center; + } + + for (Model::Engines::iterator eit = model->engines().begin(); eit != model->engines().end(); eit++) { + (*eit)->engine_location -= 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; + + // store triangles + if (primitives->triangles().size()) { + Fragment *fragment = new Fragment(Fragment::Triangles, primitives->material()); + + // add structural triangles to the fragment + for (Primitives::Triangles::iterator tris_it = primitives->triangles().begin(); tris_it != primitives->triangles().end(); tris_it++) { + Triangle *triangle = (*tris_it); + if (!triangle->detail()) { + size_t count = 0; + count += fragment->add_vertex(triangle->v0()-center, triangle->normal(), triangle->color(), false); + count += fragment->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color(), false); + count += fragment->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color(), false); + if (count == 3) + model->model_tris_count++; + } } - } - - // detail triangles - for (std::list<Triangle *>::iterator it = class_tris.begin(); it != class_tris.end(); it++) { - Triangle *triangle = (*it); - if (triangle->detail()) { - size_t count = 0; - count += VertexArray::instance()->add_vertex(triangle->v0()-center, triangle->normal(), triangle->color() ); - count += VertexArray::instance()->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color() ); - count += VertexArray::instance()->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color() ); - if (count == 3) - model->model_vertex_countdetail += count; + + // add detail triangles to the fragment + for (Primitives::Triangles::iterator tris_it = primitives->triangles().begin(); tris_it != primitives->triangles().end(); tris_it++) { + Triangle *triangle = (*tris_it); + if (triangle->detail()) { + size_t count = 0; + count += fragment->add_vertex(triangle->v0()-center, triangle->normal(), triangle->color(), true); + count += fragment->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color(), true); + count += fragment->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color(), true); + if (count == 3) { + model->model_tris_count++; + model->model_tris_detail_count++; + } + } } - delete triangle; + + // add the fragment to the model + model->fragments().push_back(fragment); } - class_tris.clear(); - // structural etriangles - model->model_first_evertex = VertexArray::instance()->index()/3; - for (std::list<Triangle *>::iterator it = class_etris.begin(); it != class_etris.end(); it++) { - Triangle *triangle = (*it); - if (!triangle->detail()) { - size_t count = 0; - count += VertexArray::instance()->add_vertex(triangle->v0()-center, triangle->normal(), triangle->color()); - count += VertexArray::instance()->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color()); - count += VertexArray::instance()->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color()); - if (count == 3) - model->model_evertex_count += count; - } - } + } + + if (model->model_tris_count + model->model_quad_count > 0) { + + } + +} - // detail etriangles - for (std::list<Triangle *>::iterator it = class_etris.begin(); it != class_etris.end(); it++) { - Triangle *triangle = (*it); - if (triangle->detail()) { - size_t count = 0; - count += VertexArray::instance()->add_vertex(triangle->v0()-center, triangle->normal(), triangle->color()); - count += VertexArray::instance()->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color()); - count += VertexArray::instance()->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color()); - if (count == 3) - model->model_evertex_countdetail += count; +Model * Map::load(std::string const &name) +{ + // open the .map file + Map 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; } - delete triangle; - } - class_etris.clear(); - - // structural ltriangles - model->model_first_lvertex = VertexArray::instance()->index()/3; - for (std::list<Triangle *>::iterator it = class_ltris.begin(); it != class_ltris.end(); it++) { - Triangle *triangle = (*it); - if (!triangle->detail()) { - size_t count = 0; - count += VertexArray::instance()->add_vertex(triangle->v0()-center, triangle->normal(), triangle->color()); - count += VertexArray::instance()->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color()); - count += VertexArray::instance()->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color()); - if (count == 3) - model->model_lvertex_count += count; + + } 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; + } - } - - // detail ltriangles - for (std::list<Triangle *>::iterator it = class_ltris.begin(); it != class_ltris.end(); it++) { - Triangle *triangle = (*it); - if (triangle->detail()) { - size_t count = 0; - count += VertexArray::instance()->add_vertex(triangle->v0()-center, triangle->normal(), triangle->color() ); - count += VertexArray::instance()->add_vertex(triangle->v1()-center, triangle->normal(), triangle->color() ); - count += VertexArray::instance()->add_vertex(triangle->v2()-center, triangle->normal(), triangle->color() ); - if (count == 3) - model->model_lvertex_countdetail += count; + + } 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; } - delete triangle; - } - class_ltris.clear(); - - // reposition lights, flares and engines - for (std::list<Light *>::iterator lit = model->model_light.begin(); lit != model->model_light.end(); lit++) { - (*lit)->light_location -= center; - } - - for (std::list<Flare *>::iterator flit = model->model_flare.begin(); flit != model->model_flare.end(); flit++) { - (*flit)->light_location -= center; - } - - for (std::list<Engine *>::iterator eit = model->model_engine.begin(); eit != model->model_engine.end(); eit++) { - (*eit)->engine_location -= center; } } - - con_print << " maps/" << model->name() << ".map " << brushes << " brushes " << model->tris() << " tris (" << model->details() << " detail)" << std::endl; + + mapfile.close(); + /* + con_print << " " << mapfile.name() << " " << mapfile.map_materials.size() << " mat" << + mapfile.map_brushes << " brushes " << + mapfile.map_faces << "/" << mapfile.map_faces_detail << " faces/detail " << std::endl; + */ + mapfile.load_fragments(model); + + con_print << " " << mapfile.name() << " " << + model->model_tris_count << "/" << model->model_tris_detail_count << " tris/detail " << + model->model_quad_count << "/" << model->model_quad_detail_count << " quads/detail " << + model->fragments().size() << " frags " <<std::endl; + + mapfile.clear_materials(); + + return model; } } diff --git a/src/model/map.h b/src/model/map.h index e5b5308..afe925b 100644 --- a/src/model/map.h +++ b/src/model/map.h @@ -13,119 +13,139 @@ #include "model/model.h" #include "model/plane.h" -#include "model/triangle.h" +#include "model/primitives.h" -namespace model { +namespace model +{ /// class to parse the .map file structure and load geometry data into a model -class Map { +class Map +{ public: /// load a .map file into a Model /** @param name name of the model to be loaded, without .map extension or maps/ prefix */ static Model *load(std::string const &name); - -protected: + +private: Map(); ~Map(); - + + /// tpye definition for a per-material list of Primitives + typedef std::map<unsigned int, Primitives *> Materials; + /// open the file for reading /** the filename will get the "maps/" prefix and ".map" suffix */ bool open(std::string const & name); - + /// parse one line, returns false on end-of-file bool getline(); - + /// current classname - inline std::string classname() const { + inline std::string classname() const + { return classname_current; } - + /// current key - inline std::string key() const { + inline std::string key() const + { return key_current; } - + /// current value - inline std::string value() const { + inline std::string value() const + { return value_current; } - + /// true if the last read line contained a new classname bool got_classname() const; - + /// true if the last read line contained a new classname bool got_classname(const char*) const; - + /// true if the last read statement was a key=value pair - inline bool got_key() const { + inline bool got_key() const + { return last_read_was_key; } - + bool got_key(const char * keylabel); - + /// check if the last read key=value pair matches keylabel and store the value in valuestring bool got_key_string(const char * keylabel, std::string & valuestring); - + /// check if the last read key=value pair matches keylabel and store the value in color bool got_key_color(const char * keylabel, math::Color & color); - + /// check if the last read key=value pair matches keylabel and store the value in f bool got_key_float(const char * keylabel, float & f); - + /// check if the last read key=value pair matches keylabel and store the value in f bool got_key_int(const char * keylabel, unsigned int & u); - + /// check if the last read key=value pair matches keylabel and store the value in valuestring bool got_key_angle(const char * keylabel, float & f); - + bool got_key_vector3f(const char * keylabel, math::Vector3f & v); - - + + /// return the number of lines read so far - inline unsigned int line() const { + inline unsigned int line() const + { return line_number; } - + /// return true of the ini file is open for reading - inline bool is_open() { return mapfile_ifs.is_open(); } - + inline bool is_open() + { + return mapfile_ifs.is_open(); + } + /// current filename - inline std::string const & name() const {return mapfile_name; } - + inline std::string const & name() const + { + return mapfile_name; + } + /// close the file void close(); - + /// generate triangles for one plane in the plane list void make_brushface(Plane *face); - - /// load parsed primitives into map fragments + + /// load parsed primitives into Model Fragments void load_fragments(Model *model); - + + /// clear the current list of per-material geometry + void clear_materials(); + /// list of planes for the current brush std::vector<Plane *> planes; - + std::string classname_current; std::string key_current; std::string value_current; - + bool last_read_was_key; bool last_read_was_classname; - - unsigned int brushes; + + unsigned int map_brushes; + unsigned int map_faces; + unsigned int map_faces_detail; + unsigned int parse_level; unsigned int line_number; std::ifstream mapfile_ifs; std::string mapfile_name; - - std::list<Triangle *> class_tris; // normal triangles - std::list<Triangle *> class_etris; // entity color triangles - std::list<Triangle *> class_ltris; // light triangles - + math::Vector3f class_maxbbox; - math::Vector3f class_minbbox; + math::Vector3f class_minbbox; + + Materials map_materials; }; } diff --git a/src/model/model.cc b/src/model/model.cc index 2e9f0ba..5becc82 100644 --- a/src/model/model.cc +++ b/src/model/model.cc @@ -12,78 +12,67 @@ namespace model { -std::map<std::string, Model*> Model::registry; +// static model registry +Model::Registry Model::model_registry; Model::Model(std::string const & name) : model_name(name) { - model_first_vertex = 0; - model_first_evertex = 0; - model_first_lvertex = 0; - - model_vertex_count = 0; - model_vertex_countdetail = 0; - model_evertex_count = 0; - model_evertex_countdetail = 0; - model_lvertex_count = 0; - model_lvertex_countdetail = 0; - model_radius = 0.5f; model_enginesound = 0; + + model_tris_detail_count = 0; + model_tris_count = 0; + model_quad_detail_count = 0; + model_quad_count = 0; } Model::~Model() { + // delete all fragments + for (Fragments::iterator fragit = model_fragments.begin(); fragit != model_fragments.end(); fragit++) { + delete(*fragit); + } + model_fragments.clear(); + // delete all engines - for (std::list<Engine *>::iterator eit = model_engine.begin(); eit != model_engine.end(); eit++) { + for (Engines::iterator eit = model_engines.begin(); eit != model_engines.end(); eit++) { delete(*eit); } - model_engine.clear(); + model_engines.clear(); // delete all lights - for (std::list<Light *>::iterator lit = model_light.begin(); lit != model_light.end(); lit++) { - delete (*lit); + for (Lights::iterator lit = model_lights.begin(); lit != model_lights.end(); lit++) { + delete(*lit); } - model_light.clear(); - + model_lights.clear(); + // delete all flares - for (std::list<Flare *>::iterator flit = model_flare.begin(); flit != model_flare.end(); flit++) { - delete (*flit); + for (Flares::iterator flit = model_flares.begin(); flit != model_flares.end(); flit++) { + delete(*flit); } - model_flare.clear(); -} - -size_t Model::tris() const -{ - return ((model_vertex_count + model_vertex_countdetail + - model_evertex_count + model_evertex_countdetail + - model_lvertex_count + model_lvertex_countdetail)/3); -} - -size_t Model::details() const -{ - return ((model_vertex_countdetail + model_evertex_countdetail + model_lvertex_countdetail)/3); + model_flares.clear(); } void Model::add_engine(Engine *engine) { - model_engine.push_back(engine); + model_engines.push_back(engine); } void Model::add_light(Light *light) { - model_light.push_back(light); + model_lights.push_back(light); } void Model::add_flare(Flare *flare) { - model_flare.push_back(flare); + model_flares.push_back(flare); } Model *Model::find(std::string const & name) { - std::map<std::string, Model*>::iterator it = registry.find(name); - if (it == registry.end()) + Registry::iterator it = model_registry.find(name); + if (it == model_registry.end()) return 0; else return (*it).second; @@ -94,40 +83,46 @@ Model *Model::load(std::string const & name) Model *model = find(name); if (!model) { model = Map::load(name); - if (model) - registry[model->name()] = model; + if (model) { + model_registry[model->name()] = model; + } } - + return model; } void Model::clear() { // delete all models in the registry - for (std::map<std::string, Model*>::iterator mit = registry.begin(); mit != registry.end(); mit++) { + for (Registry::iterator mit = model_registry.begin(); mit != model_registry.end(); mit++) { delete(*mit).second; } - registry.clear(); - + model_registry.clear(); + // clear the vertex array if (VertexArray::instance()) VertexArray::instance()->clear(); } +void Model::list_model(Model *model) +{ + con_print << " " << model->name() << " " << + model->model_tris_count << "/" << model->model_tris_detail_count << " tris/detail " << + model->model_quad_count << "/" << model->model_quad_detail_count << " quads/detail " + << model->fragments().size() << " frags "<< std::endl; +} + void Model::list() { - for (std::map<std::string, Model*>::iterator mit = registry.begin(); mit != registry.end(); mit++) { - con_print << " " << (*mit).second->name() << " " - << (*mit).second->tris() << " triangles (" - << (*mit).second->details() << " detail) " - << (*mit).second->model_engine.size() << " engines " - << (*mit).second->model_light.size() << " lights " - << (*mit).second->model_flare.size() << " flares "; + for (Registry::iterator mit = model_registry.begin(); mit != model_registry.end(); mit++) { + list_model((*mit).second); + } - con_print << registry.size() << " registered models" << std::endl; + + con_print << model_registry.size() << " registered models" << std::endl; if (VertexArray::instance()) - con_print << "vertex array " << (VertexArray::instance()->index() * 100 / VertexArray::instance()->size()) - << "% used" << std::endl; + con_print << "vertex array " << (VertexArray::instance()->index() * 100 / VertexArray::instance()->size()) + << "% of " << VertexArray::instance()->size() << " used" << std::endl; } } diff --git a/src/model/model.h b/src/model/model.h index d2b7d65..552d7dd 100644 --- a/src/model/model.h +++ b/src/model/model.h @@ -13,6 +13,7 @@ #include "math/mathlib.h" #include "model/engine.h" +#include "model/fragment.h" #include "model/light.h" #include "model/flare.h" @@ -20,15 +21,29 @@ namespace model { -/// scaling factor when loading .map geometry -const float SCALE = 1.0f / 1024.0f; - /// a 3D model contains a list of faces class Model { public: - /// load a model from disk + /// type definition for the model registry + typedef std::map<std::string, Model*> Registry; + + /// type definition for a list of model fragments + typedef std::list<Fragment *> Fragments; + + /// type definition for a list of model lights + typedef std::list<Light *> Lights; + + /// type definition for a list of model flares + typedef std::list<Flare *> Flares; + + /// type definition for a list of model engines + typedef std::list<Engine *> Engines; + + /// create a model with a name Model(std::string const & name); + + /// delete the model, and all fragments, lights, etc ~Model(); /// the name of the model @@ -36,95 +51,79 @@ public: { return model_name; } - + + /// radius + inline float radius() const + { + return model_radius; + } + + /// list of fragments + inline Fragments & fragments() + { + return model_fragments; + } + + /// list of lights + inline Lights & lights() + { + return model_lights; + } + + /// list of flares + inline Flares & flares() + { + return model_flares; + } + + /// list of engines + inline Engines & engines() + { + return model_engines; + } + /// maximum values of the bounding box - inline math::Vector3f const & maxbbox() const { return model_maxbbox; } + inline math::Vector3f const & maxbbox() const + { + return model_maxbbox; + } /// minimum values of the bounding box - inline math::Vector3f const & minbbox() const { return model_minbbox; } - - /// first vertex in the global VertexArray - inline size_t first_vertex() const { return model_first_vertex; } - - /// number of structural vertices in this model - inline size_t vertex_structural() const { return model_vertex_count; } - - /// number of detail vertices - inline size_t vertex_detail() const { return model_vertex_countdetail; } - - /// first evertex in the global VertexArray - inline size_t first_evertex() const { return model_first_evertex; } - - /// number of structural evertices in this model - inline size_t evertex_structural() const { return model_evertex_count; } - - /// number of detail evertices in this model - inline size_t evertex_detail() const { return model_evertex_countdetail; } - - /// first lvertex in the global VertexArray - inline size_t first_lvertex() const { return model_first_lvertex; } - - /// number of structural lvertices in this model - inline size_t lvertex_structural() const { return model_lvertex_count; } - - /// number of detail evertices in this model - inline size_t lvertex_detail() const { return model_lvertex_countdetail; } - + inline math::Vector3f const & minbbox() const + { + return model_minbbox; + } + /// engine sound loop for this model - inline unsigned int enginesound() const { return model_enginesound; } - - /// total number of triangles in this model - size_t tris() const; - - /// number of detail triangles in this model - size_t details() const; - - /// radius - inline float radius() const { return model_radius; } - - /// list of Engines - std::list<Engine *> model_engine; - - /// add an engine to the model - void add_engine(Engine *engine); - - /// list of Lights - std::list<Light *> model_light; - + inline unsigned int & enginesound() + { + return model_enginesound; + } + /// add a light to the model void add_light(Light *light); - - /// list of flares - std::list<Flare *> model_flare; - + + /// add an engine to the model + void add_engine(Engine *engine); + /// add a flare to the model void add_flare(Flare *flare); - std::string model_name; float model_radius; - + math::Vector3f model_maxbbox; math::Vector3f model_minbbox; - - size_t model_first_vertex; - size_t model_vertex_count; - size_t model_vertex_countdetail; - - size_t model_first_evertex; - size_t model_evertex_count; - size_t model_evertex_countdetail; - - size_t model_first_lvertex; - size_t model_lvertex_count; - size_t model_lvertex_countdetail; - + unsigned int model_enginesound; - + /* ---- static functions for the Model registry -------------------- */ - - /// the Model registry - static std::map<std::string, Model*> registry; - + + /// the model registry + static inline Registry & registry() + { + return model_registry; + } + /// get name model, returns 0 if not found static Model *find(std::string const & name); @@ -136,6 +135,28 @@ public: /// list the content of the model registry static void list(); + + /// list one model + static void list_model(Model *model); + + /// total number of triangles + size_t model_tris_count; + /// number of detail triangles + size_t model_tris_detail_count; + /// total number of quads + size_t model_quad_count; + /// number of detail quads + size_t model_quad_detail_count; + +private: + static Registry model_registry; + + std::string model_name; + + Fragments model_fragments; + Flares model_flares; + Engines model_engines; + Lights model_lights; }; } diff --git a/src/model/plane.cc b/src/model/plane.cc index a637b75..6d80df6 100644 --- a/src/model/plane.cc +++ b/src/model/plane.cc @@ -17,25 +17,25 @@ using math::Vector3f; * x*a() + y*b() + z*c() + d() = 0 */ -Plane::Plane(Vector3f const & point0, Vector3f const &point1, Vector3f const &point2) +Plane::Plane(Vector3f const & point0, Vector3f const &point1, Vector3f const &point2) { plane_detail = false; plane_surface_flags = 0; - + plane_point[0] = point0; plane_point[1] = point1; plane_point[2] = point2; - - plane_normal = crossproduct((plane_point[1] - plane_point[0]) , (plane_point[2] - plane_point[0]) ); + + plane_normal = crossproduct((plane_point[1] - plane_point[0]) , (plane_point[2] - plane_point[0])); pd = -1 * (plane_normal.x * plane_point[0].x + plane_normal.y * plane_point[0].y + plane_normal.z * plane_point[0].z); } -Plane::Plane(Plane const & other) +Plane::Plane(Plane const & other) { - for (size_t i=0; i < 3; i++) + for (size_t i=0; i < 3; i++) this->plane_point[i] = other.plane_point[i]; - - plane_normal = crossproduct((plane_point[1] - plane_point[0]) , (plane_point[2] - plane_point[0]) ); + + plane_normal = crossproduct((plane_point[1] - plane_point[0]) , (plane_point[2] - plane_point[0])); pd = -1 * (plane_normal.x * plane_point[0].x + plane_normal.y * plane_point[0].y + plane_normal.z * plane_point[0].z); } diff --git a/src/model/plane.h b/src/model/plane.h index 5a8e6b6..6c19a5a 100644 --- a/src/model/plane.h +++ b/src/model/plane.h @@ -25,28 +25,55 @@ public: Plane(math::Vector3f const & point0, math::Vector3f const &point1, math::Vector3f const &point2); /// copy constructor Plane(Plane const & other); - + /// normal of the plane, not normalized to lenght 1 - inline math::Vector3f const & normal() const { return plane_normal; } - /// the points defining the plane. + inline math::Vector3f const & normal() const + { + return plane_normal; + } + /// the points defining the plane. /// @param i 0 <= i < 3 - inline math::Vector3f const & point(size_t i) const { return plane_point[i]; } - /// plane texture - inline std::string & texture() { return plane_texture; } + inline math::Vector3f const & point(size_t i) const + { + return plane_point[i]; + } + /// plane texture + inline std::string & texture() + { + return plane_texture; + } /// first parameter of the general equation - inline float a() const { return plane_normal[0]; } + inline float a() const + { + return plane_normal[0]; + } /// second parameter of the general equation - inline float b() const { return plane_normal[1]; } + inline float b() const + { + return plane_normal[1]; + } /// third param of the general equation - inline float c() const { return plane_normal[2]; } + inline float c() const + { + return plane_normal[2]; + } /// fourth parameter of the general equation - inline float d() const { return pd; } + inline float d() const + { + return pd; + } /// indidcates if this plane was generated from a detail brush - inline bool & detail() { return plane_detail; } + inline bool & detail() + { + return plane_detail; + } /// surface flags - inline unsigned int & surface_flags() { return plane_surface_flags; } - - + inline unsigned int & surface_flags() + { + return plane_surface_flags; + } + + private: math::Vector3f plane_point[3]; math::Vector3f plane_normal; diff --git a/src/model/primitives.cc b/src/model/primitives.cc new file mode 100644 index 0000000..1b9d216 --- /dev/null +++ b/src/model/primitives.cc @@ -0,0 +1,44 @@ +/* + model/primitives.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/primitives.h" + +namespace model +{ + +Primitives::Primitives(unsigned int material) +{ + primitives_material = material; +} + +Primitives::~Primitives() +{ + // clear list of triangles + for (std::list<Triangle *>::iterator tris_it = primitives_triangles.begin(); tris_it != primitives_triangles.end(); tris_it++) + delete(*tris_it); + primitives_triangles.clear(); + + // clear list of quads + for (std::list<Quad *>::iterator quad_it = primitives_quads.begin(); quad_it != primitives_quads.end(); quad_it++) + delete(*quad_it); + primitives_quads.clear(); +} + +void Primitives::add_triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, + math::Vector3f const &normal, math::Color const &color, bool detail) +{ + Triangle *triangle = new Triangle(v0, v1, v2, normal, color, detail); + primitives_triangles.push_back(triangle); +} + +void Primitives::add_quad(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, math::Vector3f const &v3, + math::Vector3f const &normal, math::Color const &color, bool detail) +{ + Quad *quad = new Quad(v0, v1, v2, v3, normal, color, detail); + primitives_quads.push_back(quad); +} + +} diff --git a/src/model/primitives.h b/src/model/primitives.h index 28da706..d11ac61 100644 --- a/src/model/primitives.h +++ b/src/model/primitives.h @@ -7,6 +7,8 @@ #ifndef __INCLUDED_MODEL_PRIMITIVES_H__ #define __INCLUDED_MODEL_PRIMITIVES_H__ +#include <list> + #include "math/vector3f.h" #include "math/color.h" #include "model/triangle.h" @@ -15,28 +17,49 @@ namespace model { -/// a list of Triangle and Quad primitives that have to be rendered using the same material, to be parsed into fragments +/// a list of Triangle and Quad primitives with the same material, to be parsed into fragments class Primitives { public: + /// type definition for a list of triangles + typedef std::list<Triangle *> Triangles; + + /// type definition for a list of quads + typedef std::list<Quad *> Quads; + Primitives(unsigned int material); ~Primitives(); - + /// the material to be used for these primitives - inline unsigned int material() const { return primitives_material; } - + inline unsigned int material() const + { + return primitives_material; + } + + /// list of triangles + inline Triangles & triangles() + { + return primitives_triangles; + } + + /// list of quads + inline Quads & quads() + { + return primitives_quads; + } + /// add a Triangle primitive void add_triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, - math::Vector3f const &normal, math::Color const &color, bool detail); - + math::Vector3f const &normal, math::Color const &color, bool detail); + /// add a Quad primitive void add_quad(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, math::Vector3f const &v3, - math::Vector3f const &normal, math::Color const &color, bool detail); - + math::Vector3f const &normal, math::Color const &color, bool detail); + private: - std::list<Triangle *> primitives_triangles; - std::list<Quad *> primitives_quads; - + Triangles primitives_triangles; + Quads primitives_quads; + unsigned int primitives_material; }; diff --git a/src/model/quad.cc b/src/model/quad.cc index e216532..0b8b208 100644 --- a/src/model/quad.cc +++ b/src/model/quad.cc @@ -10,19 +10,18 @@ namespace model { Quad::Quad(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, math::Vector3f const &v3, - math::Vector3f const &normal, math::Color const &color, bool detail) : - quad_v0(v0), - quad_v1(v1), - quad_v2(v2), - quad_v3(v3), - quad_normal(normal), - quad_color(color) + math::Vector3f const &normal, math::Color const &color, bool detail) : + quad_v0(v0), + quad_v1(v1), + quad_v2(v2), + quad_v3(v3), + quad_normal(normal), + quad_color(color) { quad_detail = detail; } Quad::~Quad() -{ -} +{} } diff --git a/src/model/quad.h b/src/model/quad.h index d2215f2..42832d0 100644 --- a/src/model/quad.h +++ b/src/model/quad.h @@ -19,37 +19,58 @@ class Quad public: /// a new quad with 4 vertices, a normal, color and a detail flag Quad(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, math::Vector3f const &v3, - math::Vector3f const &n, math::Color const & color, bool detail); + math::Vector3f const &normal, math::Color const & color, bool detail); /// delete quad ~Quad(); - + /// normal of the quad - inline math::Vector3f const & normal() const { return quad_normal; } - - /// color of the quad - inline math::Color const & color() const { return quad_color;} - + inline math::Vector3f const & normal() const + { + return quad_normal; + } + + /// color of the quad + inline math::Color const & color() const + { + return quad_color; + } + /// indidcates if this quad was generated from a detail brush - inline bool detail() const { return quad_detail; } - + inline bool detail() const + { + return quad_detail; + } + /// quad vertex 0 - inline math::Vector3f & v0() { return quad_v0; } - + inline math::Vector3f & v0() + { + return quad_v0; + } + /// quad vertex 1 - inline math::Vector3f & v1() { return quad_v1; } - + inline math::Vector3f & v1() + { + return quad_v1; + } + /// quad vertex 2 - inline math::Vector3f & v2() { return quad_v2; } - + inline math::Vector3f & v2() + { + return quad_v2; + } + /// quad vertex 3 - inline math::Vector3f & v3() { return quad_v3; } + inline math::Vector3f & v3() + { + return quad_v3; + } private: - + math::Vector3f quad_v0; math::Vector3f quad_v1; math::Vector3f quad_v2; math::Vector3f quad_v3; - + math::Vector3f quad_normal; math::Color quad_color; bool quad_detail; diff --git a/src/model/triangle.cc b/src/model/triangle.cc index 7c36615..807d536 100644 --- a/src/model/triangle.cc +++ b/src/model/triangle.cc @@ -9,19 +9,18 @@ namespace model { -Triangle::Triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, - math::Vector3f const &normal, math::Color const &color, bool detail) : - triangle_v0(v0), - triangle_v1(v1), - triangle_v2(v2), - triangle_normal(normal), - triangle_color(color) +Triangle::Triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, + math::Vector3f const &normal, math::Color const &color, bool detail) : + triangle_v0(v0), + triangle_v1(v1), + triangle_v2(v2), + triangle_normal(normal), + triangle_color(color) { triangle_detail = detail; } Triangle::~Triangle() -{ -} +{} } diff --git a/src/model/triangle.h b/src/model/triangle.h index 9d775c4..8f4a6a5 100644 --- a/src/model/triangle.h +++ b/src/model/triangle.h @@ -19,35 +19,51 @@ class Triangle public: /// a new triangle with 3 vertices, a normal, color and a detail flag Triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, - math::Vector3f const &n, math::Color const & color, bool detail); + math::Vector3f const &normal, math::Color const & color, bool detail); /// delete triangle ~Triangle(); - + /// normal of the triangle - inline math::Vector3f const & normal() const { return triangle_normal; } - - /// color of the triangle - inline math::Color const & color() const { return triangle_color;} - + inline math::Vector3f const & normal() const + { + return triangle_normal; + } + + /// color of the triangle + inline math::Color const & color() const + { + return triangle_color; + } + /// indidcates if this triangle was generated from a detail brush - inline bool detail() const { return triangle_detail; } - + inline bool detail() const + { + return triangle_detail; + } + /// triangle vertex 0 - inline math::Vector3f & v0() { return triangle_v0; } - + inline math::Vector3f & v0() + { + return triangle_v0; + } + /// triangle vertex 1 - inline math::Vector3f & v1() { return triangle_v1; } - + inline math::Vector3f & v1() + { + return triangle_v1; + } + /// triangle vertex 2 - inline math::Vector3f & v2() { return triangle_v2; } + inline math::Vector3f & v2() + { + return triangle_v2; + } private: - + math::Vector3f triangle_v0; - /// triangle vertex 1 math::Vector3f triangle_v1; - /// triangle vertex 2 math::Vector3f triangle_v2; - + math::Vector3f triangle_normal; math::Color triangle_color; bool triangle_detail; diff --git a/src/model/vertexarray.cc b/src/model/vertexarray.cc index 6a635eb..0562bea 100644 --- a/src/model/vertexarray.cc +++ b/src/model/vertexarray.cc @@ -9,7 +9,8 @@ #include "model/vertexarray.h" #include "sys/sys.h" -namespace model { +namespace model +{ VertexArray *VertexArray::vertex_instance = 0 ; @@ -24,10 +25,10 @@ VertexArray::VertexArray(size_t size) vertex_color = (float *) malloc(vertex_size * sizeof(float)); vertex_normal = (float *) malloc(vertex_size * sizeof(float)); vertex_texture = (float *) malloc(vertex_size * sizeof(float)); - + con_print << "^BInitializing vertex array..." << std::endl; con_print << " " << size << " Mb allocated" << std::endl; - + clear(); } @@ -45,46 +46,46 @@ void VertexArray::clear() { vertex_index = 0; vertex_overflow = false; - + memset(vertex_vertex, 0, sizeof(vertex_vertex)); memset(vertex_color, 0, sizeof(vertex_color)); memset(vertex_normal, 0, sizeof(vertex_normal)); memset(vertex_texture, 0, sizeof(vertex_texture)); - + add_sphere(); } void VertexArray::add_sphere() { // load sphere vertices into the VertexArray - + // build sin/cos table float *sintable; float *costable; - + sintable = new float[SPHERESEGMENTS]; costable = new float[SPHERESEGMENTS]; float d = 2 * M_PI / (SPHERESEGMENTS-1); - + for (int i=0; i < SPHERESEGMENTS; i++) { - sintable[i] = sin( d * (float) i ); - costable[i] = cos ( d * (float) i ); + sintable[i] = sin(d * (float) i); + costable[i] = cos(d * (float) i); } - + // draw body math::Color white(1.0f, 1.0f, 1.0f); math::Vector3f v; math::Vector3f n; float texx, texy; - + int quad_count = 0; - + // add sphere for (int j=0; j < (SPHERESEGMENTS-1) / 2; j++) { - + float r = sintable[j]; float r1 = sintable[j+1]; - + for (int i = 0; i < SPHERESEGMENTS; i++) { v = math::Vector3f(r*costable[i], r*sintable[i], costable[j]); n = v; @@ -95,23 +96,23 @@ void VertexArray::add_sphere() v = math::Vector3f(r1*costable[i], r1*sintable[i], costable[j+1]); n = v; - n.normalize(); + n.normalize(); texx = (float)i/(float)(SPHERESEGMENTS-1); texy = -costable[j+1]/2 + 0.5f; add_vertex(v, n, white, texx, texy); - + quad_count++; } quad_count--; } - + // add inside-out sphere for (int j=0; j < (SPHERESEGMENTS-1) / 2; j++) { - + float r = sintable[j]; float r1 = sintable[j+1]; - + for (int i = SPHERESEGMENTS -1 ; i >= 0; i--) { v = math::Vector3f(r*costable[i], r*sintable[i], costable[j]); @@ -123,14 +124,14 @@ void VertexArray::add_sphere() v = math::Vector3f(r1*costable[i], r1*sintable[i], costable[j+1]); n = v; - n.normalize(); + n.normalize(); texx = 1-(float)i/(float)(SPHERESEGMENTS-1); texy = -costable[j+1]/2 + 0.5f; add_vertex(v, n, white, texx, texy); } } - + delete[] sintable; delete[] costable; } @@ -144,23 +145,23 @@ size_t VertexArray::add_vertex(math::Vector3f const &v, math::Vector3f const &n, } return 0; } - + for (int i = 0; i < 3; i ++) { vertex_vertex[vertex_index+i] = v[i]; vertex_normal[vertex_index+i] = n[i]; } - + vertex_color[vertex_index] = color.r; vertex_color[vertex_index+1] = color.g; vertex_color[vertex_index+2] = color.b; - + vertex_texture[vertex_index] = tex_x; vertex_texture[vertex_index+1] = tex_y; // reserved vertex_texture[vertex_index+2] = 0; - + vertex_index += 3; - + return 1; } diff --git a/src/model/vertexarray.h b/src/model/vertexarray.h index 6330d8c..37f2be9 100644 --- a/src/model/vertexarray.h +++ b/src/model/vertexarray.h @@ -10,7 +10,8 @@ #include "math/color.h" #include "math/vector3f.h" -namespace model { +namespace model +{ const int SPHERESEGMENTS=65; @@ -23,40 +24,64 @@ public: /// create a new VertexArray with size in Mb VertexArray(size_t size); ~VertexArray(); - + void clear(); - + size_t add_vertex(math::Vector3f const &v, math::Vector3f const &n, math::Color const &color, float tex_x=0.0f, float tex_y=0.0f); - - inline float *vertex() { return vertex_vertex; } - inline float *color() { return vertex_color; } - inline float *normal() { return vertex_normal; } - inline float *texture() { return vertex_texture; } - - inline bool overflow() const { return vertex_overflow; } - + + inline float *vertex() + { + return vertex_vertex; + } + inline float *color() + { + return vertex_color; + } + inline float *normal() + { + return vertex_normal; + } + inline float *texture() + { + return vertex_texture; + } + + inline bool overflow() const + { + return vertex_overflow; + } + /// number of allocated floats - inline size_t size() const { return vertex_size; } - + inline size_t size() const + { + return vertex_size; + } + /// index to the top of the stack - inline size_t index() const { return vertex_index; } - - static inline VertexArray *instance() { return vertex_instance; } - + inline size_t index() const + { + return vertex_index; + } + + static inline VertexArray *instance() + { + return vertex_instance; + } + private: /// model vertices float *vertex_vertex; float *vertex_color; float *vertex_normal; float *vertex_texture; - + size_t vertex_index; size_t vertex_size; - + void add_sphere(); - + static VertexArray *vertex_instance; - + bool vertex_overflow; }; diff --git a/src/render/draw.cc b/src/render/draw.cc index 17dbdda..54a56a0 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -8,6 +8,8 @@ #include <iomanip> #include "core/core.h" +#include "model/fragment.h" +#include "model/material.h" #include "model/model.h" #include "render/render.h" #include "render/textures.h" @@ -245,50 +247,91 @@ void draw_entity_axis(core::Entity *entity) gl::end(); } -/* ----- Entity models --------------------------------------------- */ +/* ----- model fragments ------------------------------------------- */ -void draw_model_vertex(core::Entity *entity) +void draw_fragment(model::Fragment *fragment, bool draw_details) { - size_t count = entity->model()->vertex_structural(); - if (entity->state()->detailvisible()) - count += entity->model()->vertex_detail(); - - // draw model vertices - if (count) { - size_t index = entity->model()->first_vertex(); - glDrawArrays(gl::Triangles, index, count); - Stats::tris += count/3; + size_t index = fragment->index(); + + size_t vertex_count = fragment->structural_size(); + if (draw_details) + vertex_count += fragment->detail_size(); + + switch (fragment->type()) { + case model::Fragment::Triangles: + glDrawArrays(gl::Triangles, index, vertex_count); + Stats::tris += vertex_count / 3; + break; + + case model::Fragment::Quads: + glDrawArrays(gl::Quads, index, vertex_count); + Stats::quads += vertex_count / 4; + break; } } -void draw_model_lvertex(core::Entity *entity) +void draw_model_fragments(core::Entity *entity) { - size_t count = entity->model()->lvertex_structural(); - if (entity->state()->detailvisible()) - count += entity->model()->lvertex_detail(); - - // draw model lvertices - if (count) { - gl::disable(GL_LIGHTING); - size_t index = entity->model()->first_lvertex(); - glDrawArrays(gl::Triangles, index, count); - Stats::tris += count/3; + using namespace model; + + Model *model = entity->model(); + if (!model) + return; + + // default material, lighted and geometry color + unsigned int material = Material::None; + + bool use_color_array = true; // glEnableClientState(GL_COLOR_ARRAY) is set + bool use_light = true; // gl::disable(GL_LIGHTING) is set + + for (Model::Fragments::iterator fit = model->fragments().begin(); fit != model->fragments().end(); fit++) { + + Fragment *fragment = (*fit); + + if (fragment->material() != material) { + material = fragment->material(); + + if (material & Material::Tertiary) { + if (use_color_array) { + use_color_array = false; + glDisableClientState(GL_COLOR_ARRAY); + } + // FIXME Primary, Secondary Tertiary color + math::Color color(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 (material & Material::Light) { + if (use_light) { + gl::disable(GL_LIGHTING); + use_light = false; + } + } else { + if (!use_light) { + gl::enable(GL_LIGHTING); + use_light = true; + } + } + } + + draw_fragment(fragment, entity->state()->detailvisible()); + } + + if (!use_light) { gl::enable(GL_LIGHTING); } -} -void draw_model_evertex(core::Entity *entity) -{ - size_t count = entity->model()->evertex_structural(); - if (entity->state()->detailvisible()) - count += entity->model()->evertex_detail(); - - // draw model evertices - if (count) { - size_t index = entity->model()->first_evertex(); - render::gl::color(entity->color()); - glDrawArrays(gl::Triangles, index, count); - Stats::tris += count/3; + if (!use_color_array) { + glEnableClientState(GL_COLOR_ARRAY); } } @@ -298,6 +341,8 @@ void draw_model_evertex(core::Entity *entity) /* calculate entity visibility */ void pass_prepare(float seconds) { + using namespace model; + // reset light state gl::disable(GL_LIGHT1); @@ -317,7 +362,7 @@ void pass_prepare(float seconds) // load entity models and light flare textures if (!entity->model() && entity->modelname().size()) { - entity->entity_model = model::Model::load(entity->modelname()); + entity->entity_model = Model::load(entity->modelname()); if (!entity->model()) { entity->entity_modelname.clear(); @@ -326,8 +371,8 @@ void pass_prepare(float seconds) // set entity radius to model radius entity->entity_radius = entity->entity_model->radius(); - for (std::list<model::Light *>::iterator lit = entity->model()->model_light.begin(); lit != entity->model()->model_light.end(); lit++) { - model::Light *light = (*lit); + for (Model::Lights::iterator lit = entity->model()->lights().begin(); lit != entity->model()->lights().end(); lit++) { + Light *light = (*lit); // load light texture // FIXME optimize @@ -336,8 +381,8 @@ void pass_prepare(float seconds) light->render_texture = Textures::load(flarename.str()); } - for(std::list<model::Engine*>::iterator eit = entity->model()->model_engine.begin(); eit != entity->model()->model_engine.end(); eit++) { - model::Engine *engine = (*eit); + for(Model::Engines::iterator eit = entity->model()->engines().begin(); eit != entity->model()->engines().end(); eit++) { + Engine *engine = (*eit); if (!engine->flare()) engine->engine_flare = 1; @@ -348,8 +393,8 @@ void pass_prepare(float seconds) engine->render_texture = Textures::load(flarename.str()); } - for (std::list<model::Flare *>::iterator flit = entity->model()->model_flare.begin(); flit != entity->model()->model_flare.end(); flit++) { - model::Flare *flare = (*flit); + for (Model::Flares::iterator flit = entity->model()->flares().begin(); flit != entity->model()->flares().end(); flit++) { + Flare *flare = (*flit); // load flare texture // FIXME optimize @@ -530,40 +575,19 @@ void draw_pass_default() } } -/* Draw model vertices*/ -void draw_pass_model_vertex() -{ - std::map<unsigned int, core::Entity *>::iterator it; - for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { - - core::Entity *entity = (*it).second; - if (entity->model() && entity->state()->visible()) { - gl::push(); - gl::translate(entity->state()->location()); - gl::multmatrix(entity->state()->axis()); - - draw_model_vertex(entity); - draw_model_lvertex(entity); - - gl::pop(); - } - } -} - -/* Draw entites with model evertices */ -void draw_pass_model_evertex() +/* draw model geometry fragments */ +void draw_pass_model_fragments() { std::map<unsigned int, core::Entity *>::iterator it; for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { core::Entity *entity = (*it).second; - if (entity->model() && entity->state()->visible()) { gl::push(); gl::translate(entity->state()->location()); gl::multmatrix(entity->state()->axis()); - draw_model_evertex(entity); + draw_model_fragments(entity); gl::pop(); } @@ -587,7 +611,7 @@ void draw_pass_model_fx() if (entity->model() && entity->state()->detailvisible()) { // draw model lights - for (std::list<model::Light *>::iterator lit = entity->model()->model_light.begin(); lit != entity->model()->model_light.end(); lit++) { + for (model::Model::Lights::iterator lit = entity->model()->lights().begin(); lit != entity->model()->lights().end(); lit++) { // strobe frequency t = 1.0f; @@ -630,7 +654,7 @@ void draw_pass_model_fx() } // draw flares - for (std::list<model::Flare *>::iterator flit = entity->model()->model_flare.begin(); flit != entity->model()->model_flare.end(); flit++) { + for (model::Model::Flares::iterator flit = entity->model()->flares().begin(); flit != entity->model()->flares().end(); flit++) { model::Flare *flare = (*flit); @@ -681,11 +705,11 @@ void draw_pass_model_fx() } // draw model engines for Controlable entities - if (entity->type() == core::Entity::Controlable && entity->model()->model_engine.size()) { + if (entity->type() == core::Entity::Controlable && entity->model()->engines().size()) { float u = static_cast<core::EntityControlable *>(entity)->thrust(); - for(std::list<model::Engine*>::iterator eit = entity->model()->model_engine.begin(); eit != entity->model()->model_engine.end(); eit++) { + for(model::Model::Engines::iterator eit = entity->model()->engines().begin(); eit != entity->model()->engines().end(); eit++) { model::Engine *engine = (*eit); @@ -857,17 +881,14 @@ void draw(float seconds) glEnableClientState(GL_COLOR_ARRAY); - draw_pass_model_vertex(); // draw entities with model + draw_pass_model_fragments(); glDisableClientState(GL_COLOR_ARRAY); - - draw_pass_model_evertex(); // draw entities with model, vertices with entity color - - gl::enable(GL_BLEND); gl::disable(GL_LIGHTING); - + + gl::enable(GL_BLEND); + draw_pass_spacegrid(); // draw the blue spacegrid - Dust::draw(); // draw spacedust draw_pass_model_fx(); // draw entity lights and engines |