diff options
-rw-r--r-- | src/model/asefile.cc | 115 | ||||
-rw-r--r-- | src/model/asefile.h | 12 | ||||
-rw-r--r-- | src/model/fragment.cc | 11 | ||||
-rw-r--r-- | src/model/fragment.h | 4 | ||||
-rw-r--r-- | src/model/map.cc | 13 | ||||
-rw-r--r-- | src/model/material.cc | 38 | ||||
-rw-r--r-- | src/model/material.h | 50 | ||||
-rw-r--r-- | src/model/triangle.h | 24 | ||||
-rw-r--r-- | src/render/draw.cc | 56 |
9 files changed, 272 insertions, 51 deletions
diff --git a/src/model/asefile.cc b/src/model/asefile.cc index 7b574d7..f4f3342 100644 --- a/src/model/asefile.cc +++ b/src/model/asefile.cc @@ -33,6 +33,11 @@ ASEFile::ASEFile(std::string const &name) ASEFile::~ASEFile() { + for (VertexList::iterator it = ase_tvertexlist.begin(); it != ase_tvertexlist.end(); it++) { + delete (*it).second; + } + ase_tvertexlist.clear(); + for (VertexList::iterator it = ase_vertexlist.begin(); it != ase_vertexlist.end(); it++) { delete (*it).second; } @@ -126,7 +131,7 @@ bool ASEFile::read_mesh_face_list(std::istream &is) line >> word; if (word.compare("}") == 0) { - con_debug << count << " mesh faces" << std::endl; + con_debug << " " << count << " mesh faces" << std::endl; return true; } else if ( word.compare("*MESH_FACE") == 0) { @@ -160,6 +165,8 @@ bool ASEFile::read_mesh_normals(std::istream &is) char data[1024]; memset(data, 0, sizeof(data)); + size_t count = 0; + size_t index = 0; size_t vertindex = 0; float x, y, z; @@ -172,6 +179,7 @@ bool ASEFile::read_mesh_normals(std::istream &is) line >> firstword; if (firstword.compare("}") == 0) { + con_debug << " " << count << " face normals" << std::endl; return true; } else if ( firstword.compare("*MESH_FACENORMAL") == 0) { @@ -179,6 +187,7 @@ bool ASEFile::read_mesh_normals(std::istream &is) it = ase_facelist.find(index); if (it != ase_facelist.end()) { (*it).second->normal().assign(x, y, z); + count++; } else { con_debug << " could not find face " << index << std::endl; } @@ -205,6 +214,76 @@ bool ASEFile::read_mesh_normals(std::istream &is) return false; } +bool ASEFile::read_mesh_tvertex_list(std::istream &is) +{ + size_t count = 0; + + char data[1024]; + memset(data, 0, sizeof(data)); + + while (is.getline(data, sizeof(data) -1 )) { + std::istringstream line(data); + + std::string firstword; + line >> firstword; + + if (firstword.compare("}") == 0) { + con_debug << " " << count << " texture vertices" << std::endl; + return true; + + } else if ( firstword.compare("*MESH_TVERT") == 0) { + size_t index; + float x, y, z; + if (line >> index >> x >> y >> z) { + math::Vector3f *v = new math::Vector3f(x, y, z); + ase_tvertexlist[index] = v; + count++; + } + } + } + + return false; +} + +bool ASEFile::read_mesh_tface_list(std::istream &is) +{ +size_t count = 0; + + char data[1024]; + memset(data, 0, sizeof(data)); + + while (is.getline(data, sizeof(data) -1 )) { + std::istringstream line(data); + + std::string firstword; + line >> firstword; + + if (firstword.compare("}") == 0) { + con_debug << " " << count << " face texture coordinates" << std::endl; + return true; + + } else if ( firstword.compare("*MESH_TFACE") == 0) { + size_t index, a, b, c; + if (line >> index >> a >> b >> c) { + Triangle *triangle = ase_facelist[index]; + math::Vector3f *t0 = ase_tvertexlist[a]; + math::Vector3f *t1 = ase_tvertexlist[b]; + math::Vector3f *t2 = ase_tvertexlist[c]; + if (triangle) { + if (t0) + triangle->t0().assign(t0->x, t0->y); + if (t1) + triangle->t1().assign(t1->x, t1->y); + if (t2) + triangle->t2().assign(t2->x, t2->y); + } + count++; + } + } + } + + return false; +} bool ASEFile::read_mesh(std::istream &is) { @@ -238,6 +317,18 @@ bool ASEFile::read_mesh(std::istream &is) read_mesh_normals(is); } + } else if ((level == 1 ) && (word.compare("*MESH_TVERTLIST") == 0)) { + if ((line >> word) && (word.compare("{") == 0)) { + con_debug << " " << name() << " *MESH_TVERTLIST" << std::endl; + read_mesh_tvertex_list(is); + } + + } else if ((level == 1 ) && (word.compare("*MESH_TFACELIST") == 0)) { + if ((line >> word) && (word.compare("{") == 0)) { + con_debug << " " << name() << " *MESH_TFACELIST" << std::endl; + read_mesh_tface_list(is); + } + } else { do { @@ -337,11 +428,12 @@ Model * ASEFile::load(const std::string &name) Model *model = new Model(name); // default material - Material *material = Material::find("textures/common/entity"); + Material *material = Material::find("models/" + name); if (!material) { - material = new Material("placeholder"); + material = new Material("models/" + name); Material::add(material); - material->set_flags(Material::Primary); + material->set_flags(Material::Texture); + material->set_texture(material->name()); } // a single fragment for all the model triangles @@ -353,18 +445,21 @@ Model * ASEFile::load(const std::string &name) // calculate model center math::Vector3f center((asefile.ase_minbbox + asefile.ase_maxbbox) * 0.5f); - model->model_minbbox = asefile.ase_minbbox - center; - model->model_maxbbox = asefile.ase_maxbbox - center; + //const float scale = SCALE; + const float scale = 0.125f; - model->model_radius = asefile.ase_minbbox.length(); + // caculate bounding box + model->model_minbbox = (asefile.ase_minbbox - center) * scale; + model->model_maxbbox = (asefile.ase_maxbbox - center) * scale; + model->model_radius = model->model_maxbbox.length(); // load the model faces into the fragment for (FaceList::iterator it = asefile.ase_facelist.begin(); it != asefile.ase_facelist.end(); it++) { Triangle *triangle = (*it).second; - fragment->add_vertex(triangle->v0() - center , triangle->n0(), false); - fragment->add_vertex(triangle->v1() - center , triangle->n1(), false); - fragment->add_vertex(triangle->v2() - center , triangle->n2(), false); + fragment->add_vertex((triangle->v0() - center) * scale , triangle->n0(), triangle->t0(), false); + fragment->add_vertex((triangle->v1() - center) * scale , triangle->n1(), triangle->t1(), false); + fragment->add_vertex((triangle->v2() - center) * scale , triangle->n2(), triangle->t2(), false); model->model_tris_count++; model->model_tris_detail_count++; diff --git a/src/model/asefile.h b/src/model/asefile.h index 7f5ab03..dc1516b 100644 --- a/src/model/asefile.h +++ b/src/model/asefile.h @@ -55,6 +55,16 @@ private: bool read_mesh_vertex_list(std::istream &is); /** + * @brief read *MESH_TVERTLIST + */ + bool read_mesh_tvertex_list(std::istream &is); + + /** + * @brief read *MESH_TFACELIST + */ + bool read_mesh_tface_list(std::istream &is); + + /** * @brief read *MESH */ bool read_mesh(std::istream &is); @@ -84,6 +94,8 @@ private: VertexList ase_vertexlist; + VertexList ase_tvertexlist; + FaceList ase_facelist; math::Vector3f ase_maxbbox; diff --git a/src/model/fragment.cc b/src/model/fragment.cc index 7765b7e..72d8e2a 100644 --- a/src/model/fragment.cc +++ b/src/model/fragment.cc @@ -37,6 +37,17 @@ size_t Fragment::add_vertex(math::Vector3f const & vertex, math::Vector3f const return n; } +size_t Fragment::add_vertex(math::Vector3f const & vertex, math::Vector3f const &normal, math::Vector2f const &texcoord, bool detail) +{ + size_t n = VertexArray::instance()->add_vertex(vertex, normal, texcoord.x, texcoord.y); + if (n) { + if (detail) + fragment_detail_size += n; + else + fragment_structural_size += n; + } + return n; +} /* ---- class FragmentGroup ---------------------------------------- */ FragmentGroup::FragmentGroup() diff --git a/src/model/fragment.h b/src/model/fragment.h index e975734..9d992e1 100644 --- a/src/model/fragment.h +++ b/src/model/fragment.h @@ -11,6 +11,7 @@ #include "math/axis.h" #include "math/vector3f.h" +#include "math/vector2f.h" #include "model/material.h" namespace model @@ -28,6 +29,9 @@ public: /// add a vertex to the fragment size_t add_vertex(math::Vector3f const & vertex, math::Vector3f const &normal, bool detail); + + /// add a vertex to the fragment + size_t add_vertex(math::Vector3f const & vertex, math::Vector3f const &normal, math::Vector2f const &texcoord, bool detail); /// the type of primitives this fragment consists of inline Type type() const diff --git a/src/model/map.cc b/src/model/map.cc index 8165e3a..9cb5295 100644 --- a/src/model/map.cc +++ b/src/model/map.cc @@ -434,16 +434,13 @@ void Map::make_brushface(Plane *face) if (vl.size() > 2) { - Material *material = Material::find(face->texture()); + Material *material = Material::find("textures/" + face->texture()); + if (!material) { - material = new Material(face->texture()); + material = new Material("textures/" + face->texture()); Material::add(material); - material->set_color(math::Color(1.0, 0.0f, 1.0f)); - material->set_flags(Material::Bright); - - // don't show material warnings on a dedicated server - if (VertexArray::instance()) - con_warn << "Unkown material '" << face->texture() << "'" << std::endl; + material->set_flags(Material::Texture); + material->set_texture(material->name()); } // find the list if primitives for the current material, allocate a new one if necessary diff --git a/src/model/material.cc b/src/model/material.cc index 81adfae..7d278f9 100644 --- a/src/model/material.cc +++ b/src/model/material.cc @@ -19,6 +19,7 @@ Material::Material(const std::string &name) : material_name(name), material_colo { aux::to_lowercase(material_name); material_flags = 0; + material_texture_id = 0; } Material::~Material() @@ -31,6 +32,16 @@ void Material::set_color(const math::Color &color) material_color.a = 1.0f; } +void Material::set_texture(const std::string &texture) +{ + material_texture.assign(texture); +} + +void Material::set_texture_id(const size_t texture_id) +{ + material_texture_id = texture_id; +} + Material::Registry Material::material_registry; void Material::init() @@ -113,17 +124,14 @@ void Material::load_shader(const std::string &shadername) } else if ((firstword.size()) && (parselevel == 0) ) { - if (firstword.compare(0, 9, "textures/") == 0) { - firstword.erase(0, 9); - material = find(firstword); - if (material) { - con_warn << "Duplicate material '" << firstword << "'" << std::endl; - } else { - material = new Material(firstword); - add(material); - //con_debug << " " << firstword << std::endl; - } + material = find(firstword); + if (material) { + con_warn << "Duplicate material '" << firstword << "'" << std::endl; + } else { + material = new Material(firstword); + add(material); count++; + //con_debug << " " << firstword << std::endl; } } else if ((parselevel == 1) && (material)) { @@ -151,6 +159,16 @@ void Material::load_shader(const std::string &shadername) continue; } else if (firstword.compare("qer_trans") == 0) { continue; + } else if (firstword.compare("texture") == 0) { + + // texture name should not contain spaces + if (linestream >> firstword) { + material->set_texture(firstword); + material->set_flags(Material::Texture); + } else { + con_warn << shaderfile.name() << " texture key without filename at line " << linenumber << std::endl; + } + } else { con_warn << shaderfile.name() << " unknown key '" << firstword << "' at line " << linenumber << std::endl; diff --git a/src/model/material.h b/src/model/material.h index a2ba0d6..9072a4d 100644 --- a/src/model/material.h +++ b/src/model/material.h @@ -20,20 +20,35 @@ class Material { public: /// surface flags - enum SurfaceFlags { None=0, Primary=1, Secondary=2, Tertiary=3, Bright=4, Engine=8, Environment=16}; + enum SurfaceFlags { None=0, Primary=1, Secondary=2, Tertiary=3, Bright=4, Engine=8, Environment=16, Texture=32}; /// type definition for the material registry typedef std::map<std::string, Material *> Registry; Material(const std::string &name); + ~Material(); + /* ---- inspectors ----------------------------------------- */ + inline const std::string &name() const { return material_name; } inline const math::Color &color() const { return material_color; } inline const unsigned int flags() const { return material_flags; } + inline const std::string &texture() const { return material_texture; } + + inline const size_t texture_id() const { return material_texture_id; } + + /* ---- mutators ------------------------------------------- */ + + void set_color(const math::Color &color); + + void set_texture(const std::string &texture); + + void set_texture_id(const size_t texture_id); + inline void set_flags(SurfaceFlags flags) { material_flags |= flags; @@ -43,31 +58,38 @@ public: { material_flags &= ~flags; } - - - void set_color(const math::Color &color); -/* ---- static ----------------------------------------------------- */ + /* ---- static ----------------------------------------------------- */ /** - * @brief initialize materials - * reads materials from the shader files + * @brief initialize material registry + * reads materials from the shader files listed in shaderlist.txt */ static void init(); - /// clear all materials + /** + * @brief shutdown material registry + */ static void shutdown(); - /// clear all materials + /** + * @brief clear material registry + */ static void clear(); - /// list registered materials + /** + * @brief print registered materials to the system console + */ static void list(); - /// add a material to the registry + /** + * @brief add a material to the registry + */ static void add(Material *material); - /// find a material in the registry + /** + * @brief find a material in the registry + */ static Material *find(const std::string &name); private: @@ -75,8 +97,10 @@ private: std::string material_name; math::Color material_color; unsigned int material_flags; + std::string material_texture; + size_t material_texture_id; - /// the material registry + /// the materials registry static Registry material_registry; static void load_shader(const std::string &shadername); diff --git a/src/model/triangle.h b/src/model/triangle.h index fe1c720..a3fb643 100644 --- a/src/model/triangle.h +++ b/src/model/triangle.h @@ -8,6 +8,7 @@ #define __INCLUDED_MODEL_TRIANGLE_H__ #include "math/color.h" +#include "math/vector2f.h" #include "math/vector3f.h" namespace model @@ -78,6 +79,12 @@ public: return triangle_n0; } + /// triangle vertex 0 texture coordinates + inline math::Vector2f & t0() + { + return triangle_t0; + } + /// triangle vertex 1 inline math::Vector3f & v1() { @@ -89,6 +96,12 @@ public: { return triangle_n1; } + + /// triangle vertex 1 texture coordinates + inline math::Vector2f & t1() + { + return triangle_t1; + } /// triangle vertex 2 inline math::Vector3f & v2() @@ -96,22 +109,31 @@ public: return triangle_v2; } - /// triangle vertex 0 normal + /// triangle vertex 2 normal inline math::Vector3f & n2() { return triangle_n2; } + /// triangle vertex 2 texture coordinates + inline math::Vector2f & t2() + { + return triangle_t2; + } + private: math::Vector3f triangle_v0; math::Vector3f triangle_n0; + math::Vector2f triangle_t0; math::Vector3f triangle_v1; math::Vector3f triangle_n1; + math::Vector2f triangle_t1; math::Vector3f triangle_v2; math::Vector3f triangle_n2; + math::Vector2f triangle_t2; math::Vector3f triangle_normal; bool triangle_detail; diff --git a/src/render/draw.cc b/src/render/draw.cc index 4392f87..c4c18c3 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -564,8 +564,9 @@ void draw_model_fragments(model::Model *model, { // default material, lighted and geometry color const model::Material *material = 0; - math::Color color(1.0f, 0.0f, 1.0f); // current drawing color + math::Color color(1.0f, 1.0f, 1.0f); // current drawing color bool use_light = true; // gl::disable(GL_LIGHTING) is set + bool use_texture = false; // texturing bool use_env = false; // environment mapping //bool use_color_array = true; // glEnableClientState(GL_COLOR_ARRAY) is set @@ -601,7 +602,7 @@ void draw_model_fragments(model::Model *model, use_color_array = false; }*/ - gl::color(model->enginecolor() * thrust); + color.assign(model->enginecolor() * thrust); } else if (material->flags() & model::Material::Tertiary) { /* if (use_color_array) { @@ -648,26 +649,55 @@ void draw_model_fragments(model::Model *model, } } + if (material->flags() & model::Material::Texture) { + + Textures::bind(material->texture()); + + if (!use_texture) { + gl::enable(GL_TEXTURE_2D); + use_texture = true; + } + + } + if (material->flags() & model::Material::Environment) { - if (!use_env && core::localplayer()->zone()->sky_texture()) { - Textures::bind(core::localplayer()->zone()->sky_texture()); + + if (!(material->flags() & model::Material::Texture)) { + // use sky as envmap if the material defines no texture + if (core::localplayer()->zone()->sky_texture()) { + Textures::bind(core::localplayer()->zone()->sky_texture()); + gl::enable(GL_TEXTURE_2D); + use_texture = true; + } else if (use_texture) { + gl::disable(GL_TEXTURE_2D); + use_texture = false; + } + } + if (!use_env) { // enable env mapping - gl::enable(GL_TEXTURE_2D); gl::enable(GL_TEXTURE_GEN_S); gl::enable(GL_TEXTURE_GEN_T); use_env = true; } + } else { + if (use_env) { // disable env mapping gl::disable(GL_TEXTURE_GEN_S); gl::disable(GL_TEXTURE_GEN_T); - gl::disable(GL_TEXTURE_2D); use_env = false; } } + if (!(material->flags() & (model::Material::Texture + model::Material::Environment))) { + if (use_texture) { + gl::disable(GL_TEXTURE_2D); + use_texture = false; + } + } + } else { // material not found @@ -681,9 +711,14 @@ void draw_model_fragments(model::Model *model, // disable env mapping gl::disable(GL_TEXTURE_GEN_S); gl::disable(GL_TEXTURE_GEN_T); - gl::disable(GL_TEXTURE_2D); use_env = false; } + + if (use_texture) { + gl::disable(GL_TEXTURE_2D); + use_texture = false; + } + /* if (!use_color_array) { glEnableClientState(GL_COLOR_ARRAY); use_color_array = true; @@ -707,13 +742,16 @@ void draw_model_fragments(model::Model *model, if (use_env) { // disable env mapping - gl::disable(GL_TEXTURE_2D); gl::disable(GL_TEXTURE_GEN_S); gl::disable(GL_TEXTURE_GEN_T); - use_env = false; } + if (use_texture) { + gl::disable(GL_TEXTURE_2D); + use_texture = false; + } + /* if (!use_color_array) { glEnableClientState(GL_COLOR_ARRAY); }*/ |