From bbd04914749b2e3918796fe331daf649b06163ea Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 9 Aug 2009 21:11:55 +0000 Subject: adds r_normals cvar, read normals from .ase models --- src/model/asefile.cc | 200 +++++++++++++++++++++++++++++++++++--------------- src/model/asefile.h | 16 ++-- src/model/triangle.cc | 31 +++++--- src/model/triangle.h | 39 +++++++--- src/render/draw.cc | 32 ++++++-- src/render/render.cc | 4 + src/render/render.h | 2 + 7 files changed, 233 insertions(+), 91 deletions(-) (limited to 'src') diff --git a/src/model/asefile.cc b/src/model/asefile.cc index a267d9b..7b574d7 100644 --- a/src/model/asefile.cc +++ b/src/model/asefile.cc @@ -33,8 +33,16 @@ ASEFile::ASEFile(std::string const &name) ASEFile::~ASEFile() { + for (VertexList::iterator it = ase_vertexlist.begin(); it != ase_vertexlist.end(); it++) { + delete (*it).second; + } ase_vertexlist.clear(); + for (FaceList::iterator it = ase_facelist.begin(); it != ase_facelist.end(); it++) { + delete (*it).second; + } + ase_facelist.clear(); + if (asefile_ifs.is_open()) asefile_ifs.close(); } @@ -63,22 +71,49 @@ bool ASEFile::read_header(std::istream &is) return true; } -bool ASEFile::read_mesh_face_list(std::istream &is) +bool ASEFile::read_mesh_vertex_list(std::istream &is) { - Material *material = Material::find("ase_placeholder"); - if (!material) { - material = new Material("ase_placeholder"); - Material::add(material); - //material->set_color(math::Color(0.8, 0.8f, 0.8f)); - material->set_flags(Material::Primary); + 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 << " mesh vertices" << std::endl; + + return true; + + } else if ( firstword.compare("*MESH_VERTEX") == 0) { + size_t index; + float x, y, z; + if (line >> index >> x >> y >> z) { + math::Vector3f *v = new math::Vector3f(x, y, z); + ase_vertexlist[index] = v; + + for (size_t i = 0; i < 3; i++) { + if ((*v)[i] > ase_maxbbox[i]) { + ase_maxbbox[i] = (*v)[i]; + } + if ((*v)[i] < ase_minbbox[i]) { + ase_minbbox[i] = (*v)[i]; + } + } + count++; + } + } } - Fragment *fragment = new Fragment(Fragment::Triangles, material); - - FragmentGroup *group = new FragmentGroup(); - group->set_type(FragmentGroup::None); - group->push_back(fragment); + return false; +} +bool ASEFile::read_mesh_face_list(std::istream &is) +{ size_t count = 0; char data[1024]; @@ -92,48 +127,44 @@ bool ASEFile::read_mesh_face_list(std::istream &is) if (word.compare("}") == 0) { con_debug << count << " mesh faces" << std::endl; - - model->add_group(group); - return true; } else if ( word.compare("*MESH_FACE") == 0) { + std::string facestr; size_t a, b, c; - if ( (line >> word) && + if ( (line >> facestr) && (line >> word) && (line >> a) && (line >> word) && (line >> b) && (line >> word) && (line >> c)) { - - math::Vector3f n(ase_vertexlist[a]); - n.normalize(); - fragment->add_vertex(ase_vertexlist[a], n, false); - - n.assign(ase_vertexlist[b]); - n.normalize(); - fragment->add_vertex(ase_vertexlist[b], n, false); - n.assign(ase_vertexlist[c]); - n.normalize(); - fragment->add_vertex(ase_vertexlist[c], n, false); + if (facestr.size() && facestr[facestr.size()-1] == ':') { + facestr.erase(facestr.size()-1); + } - model->model_tris_count++; - model->model_tris_detail_count++; + size_t index; + std::istringstream faceindexstr(facestr); + faceindexstr >> index; + + Triangle *triangle = new Triangle(*ase_vertexlist[a], *ase_vertexlist[b], *ase_vertexlist[c]); + ase_facelist[index] = triangle; } count++; } } - delete group; return false; } -bool ASEFile::read_mesh_vertex_list(std::istream &is) +bool ASEFile::read_mesh_normals(std::istream &is) { - size_t count = 0; - char data[1024]; memset(data, 0, sizeof(data)); + size_t index = 0; + size_t vertindex = 0; + float x, y, z; + FaceList::iterator it; + while (is.getline(data, sizeof(data) -1 )) { std::istringstream line(data); @@ -141,26 +172,33 @@ bool ASEFile::read_mesh_vertex_list(std::istream &is) line >> firstword; if (firstword.compare("}") == 0) { - con_debug << count << " mesh vertices" << std::endl; - return true; - } else if ( firstword.compare("*MESH_VERTEX") == 0) { - size_t index; - float x, y, z; + } else if ( firstword.compare("*MESH_FACENORMAL") == 0) { if (line >> index >> x >> y >> z) { - math::Vector3f v(x, y, z); - ase_vertexlist[index] = v; - - for (size_t i = 0; i < 3; i++) { - if (v[i] > ase_maxbbox[i]) { - ase_maxbbox[i] = v[i]; - } - if (v[i] < ase_minbbox[i]) { - ase_minbbox[i] = v[i]; - } + it = ase_facelist.find(index); + if (it != ase_facelist.end()) { + (*it).second->normal().assign(x, y, z); + } else { + con_debug << " could not find face " << index << std::endl; } - count++; + vertindex = 0; + } else { + it = ase_facelist.end(); + } + } else if ( firstword.compare("*MESH_VERTEXNORMAL") == 0) { + + if ( (it != ase_facelist.end()) && (line >> index >> x >> y >> z)) { + + if (vertindex == 0) { + (*it).second->n0().assign(x, y, z); + } else if (vertindex == 1) { + (*it).second->n1().assign(x, y, z); + } else if (vertindex == 2) { + (*it).second->n2().assign(x, y, z); + } + + vertindex++; } } } @@ -187,12 +225,19 @@ bool ASEFile::read_mesh(std::istream &is) con_debug << " " << name() << " *MESH_VERTEX_LIST" << std::endl; read_mesh_vertex_list(is); } + } else if ((level == 1 ) && (word.compare("*MESH_FACE_LIST") == 0)) { if ((line >> word) && (word.compare("{") == 0)) { con_debug << " " << name() << " *MESH_FACE_LIST" << std::endl; read_mesh_face_list(is); } + } else if ((level == 1 ) && (word.compare("*MESH_NORMALS") == 0)) { + if ((line >> word) && (word.compare("{") == 0)) { + con_debug << " " << name() << " *MESH_NORMALS" << std::endl; + read_mesh_normals(is); + } + } else { do { @@ -271,12 +316,6 @@ bool ASEFile::read() } } - // TODO CENTER - model->model_minbbox = ase_minbbox; - model->model_maxbbox = ase_maxbbox; - - model->model_radius = math::max(ase_minbbox.length(), ase_maxbbox.length()); - return true; } @@ -288,16 +327,55 @@ Model * ASEFile::load(const std::string &name) return 0; } - asefile.model = new Model(name); + if (!asefile.read()) { + return 0; + } + + if (!asefile.ase_facelist.size()) + return 0; - con_debug << " " << asefile.name() << std::endl; + Model *model = new Model(name); - if (!asefile.read()) { - delete asefile.model; - asefile.model = 0; + // default material + Material *material = Material::find("textures/common/entity"); + if (!material) { + material = new Material("placeholder"); + Material::add(material); + material->set_flags(Material::Primary); + } + + // a single fragment for all the model triangles + Fragment *fragment = new Fragment(Fragment::Triangles, material); + FragmentGroup *group = new FragmentGroup(); + group->set_type(FragmentGroup::None); + group->push_back(fragment); + + // 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; + + model->model_radius = asefile.ase_minbbox.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); + + model->model_tris_count++; + model->model_tris_detail_count++; } - return asefile.model; + model->add_group(group); + + con_debug << " " << asefile.name() << " " << asefile.ase_vertexlist.size() << " vertices " << + model->model_tris_count << "/" << model->model_tris_detail_count << " faces/detail" << std::endl; + + return model; } } // namespace model diff --git a/src/model/asefile.h b/src/model/asefile.h index bb731b7..7f5ab03 100644 --- a/src/model/asefile.h +++ b/src/model/asefile.h @@ -10,6 +10,7 @@ #include "math/vector3f.h" #include "model/model.h" +#include "model/triangle.h" #include "filesystem/filestream.h" #include @@ -31,11 +32,18 @@ public: private: - typedef std::map VertexList; + typedef std::map VertexList; + + typedef std::map FaceList; ASEFile(std::string const &name); ~ASEFile(); + /** + * @brief read *MESH_NORMALS + */ + bool read_mesh_normals(std::istream &is); + /** * @brief read *MESH_FACE_LIST */ @@ -76,13 +84,11 @@ private: VertexList ase_vertexlist; + FaceList ase_facelist; + math::Vector3f ase_maxbbox; math::Vector3f ase_minbbox; - - math::Vector3f ase_center; - - Model *model; }; } // namespace model diff --git a/src/model/triangle.cc b/src/model/triangle.cc index a649fdd..429c1d9 100644 --- a/src/model/triangle.cc +++ b/src/model/triangle.cc @@ -9,6 +9,11 @@ namespace model { +Triangle::Triangle() +{ + triangle_detail = false; +} + Triangle::Triangle( math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, math::Vector3f const &normal, bool detail) : @@ -23,17 +28,10 @@ Triangle::Triangle( triangle_detail = detail; } -Triangle::Triangle(math::Vector3f const &v0, math::Vector3f const &n0, - math::Vector3f const &v1, math::Vector3f const &n1, - math::Vector3f const &v2, math::Vector3f const &n2, - math::Vector3f const &normal) : +Triangle::Triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2) : triangle_v0(v0), - triangle_n0(n0), triangle_v1(v1), - triangle_n1(n1), - triangle_v2(v2), - triangle_n2(n2), - triangle_normal(normal) + triangle_v2(v2) { triangle_detail = false; } @@ -41,4 +39,19 @@ Triangle::Triangle(math::Vector3f const &v0, math::Vector3f const &n0, Triangle::~Triangle() {} +void Triangle::assign(const Triangle &other) +{ + triangle_v0.assign(other.triangle_v0); + triangle_n0.assign(other.triangle_n0); + + triangle_v1.assign(other.triangle_v1); + triangle_n1.assign(other.triangle_n1); + + triangle_v2.assign(other.triangle_v2); + triangle_n2.assign(other.triangle_n2); + + triangle_normal.assign(other.triangle_normal); + triangle_detail = other.triangle_detail; +} + } diff --git a/src/model/triangle.h b/src/model/triangle.h index 27abeed..fe1c720 100644 --- a/src/model/triangle.h +++ b/src/model/triangle.h @@ -17,24 +17,45 @@ namespace model class Triangle { public: - /// a new triangle with 3 vertices, a normal and detail flag - Triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, - math::Vector3f const &normal, bool detail); + /** + * @brief default constructor + */ + Triangle(); /** - * @brief a new triangle with 3 vertices with normals and a face normal + * @brief copy constructor + */ + Triangle(const Triangle &other); + + /** + * @brief a new triangle with 3 vertices * this constructor sets the detail flag to false */ - Triangle( math::Vector3f const &v0, math::Vector3f const &n0, - math::Vector3f const &v1, math::Vector3f const &n1, - math::Vector3f const &v2, math::Vector3f const &n2, - math::Vector3f const &normal); + Triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2); + + /// a new triangle with 3 vertices, a normal and detail flag + Triangle(math::Vector3f const &v0, math::Vector3f const &v1, math::Vector3f const &v2, + math::Vector3f const &normal, bool detail); /// delete triangle ~Triangle(); + /** + * @brief assignment + */ + void assign(const Triangle &other); + + /** + * @brief assignment oeprator + */ + inline const Triangle & operator=(const Triangle &other) + { + assign(other); + return (*this); + } + /// normal of the triangle - inline math::Vector3f const & normal() const + inline math::Vector3f & normal() { return triangle_normal; } diff --git a/src/render/draw.cc b/src/render/draw.cc index 52933b7..4392f87 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -535,6 +535,27 @@ void draw_fragment(model::Fragment *fragment, bool draw_details) Stats::quads += vertex_count / 4; break; } + + if (r_normals->value()) { + gl::begin(gl::Lines ); + + gl::color(1.0f, 0.0f, 0.0f); + + const float s = 0.1f; + + const float *n = core::game()->vertexarray()->normal() + index * 3; + const float *v = core::game()->vertexarray()->vertex() + index * 3; + + for (size_t i = 0; i < vertex_count; i++) { + gl::normal(-n[i*3], -n[i*3 +1 ], -n[i*3 +2]); + gl::vertex(v[i*3], v[i*3 +1 ], v[i*3 +2]); + + gl::normal(n[i*3], n[i*3 +1 ], n[i*3 +2]); + gl::vertex(v[i*3] + n[i*3] * s, v[i*3 +1] + n[i*3 +1] * s, v[i*3 +2] + n[i*3+2] * s); + } + gl::end(); + } + } void draw_model_fragments(model::Model *model, @@ -543,6 +564,7 @@ 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 bool use_light = true; // gl::disable(GL_LIGHTING) is set bool use_env = false; // environment mapping //bool use_color_array = true; // glEnableClientState(GL_COLOR_ARRAY) is set @@ -587,8 +609,6 @@ void draw_model_fragments(model::Model *model, glDisableClientState(GL_COLOR_ARRAY); }*/ - math::Color color; - if ((material->flags() & model::Material::Tertiary) == model::Material::Tertiary) { for (size_t i = 0; i < 3; i++) color[i] = (color_primary[i] + color_secondary[i]) / 2; @@ -603,15 +623,12 @@ void draw_model_fragments(model::Model *model, color.r *= material->color().r; color.g *= material->color().g; color.b *= material->color().b; - - gl::color(color); - } else { /* if (!use_color_array) { glEnableClientState(GL_COLOR_ARRAY); use_color_array = true; }*/ - gl::color(material->color()); + color.assign(material->color()); } if (power && (material->flags() & model::Material::Bright)) { @@ -671,10 +688,11 @@ void draw_model_fragments(model::Model *model, glEnableClientState(GL_COLOR_ARRAY); use_color_array = true; }*/ - gl::color(1.0f, 0.0f, 1.0f); + color.assign(1.0f, 0.0f, 1.0f); } } + gl::color(color); draw_fragment(fragment, detail); } diff --git a/src/render/render.cc b/src/render/render.cc index ce23645..e37f5f2 100644 --- a/src/render/render.cc +++ b/src/render/render.cc @@ -34,6 +34,7 @@ core::Cvar *r_sky = 0; core::Cvar *r_wireframe = 0; core::Cvar *r_mipmap = 0; core::Cvar *r_collision = 0; +core::Cvar *r_normals = 0; void func_list_textures(std::string const &args) { @@ -68,6 +69,9 @@ void init(int width, int height) r_wireframe = core::Cvar::get("r_wireframe", "0", core::Cvar::Archive); r_wireframe->set_info("[bool] render wireframe"); + r_normals = core::Cvar::get("r_normals", "0", core::Cvar::Archive); + r_normals->set_info("[bool] render face normals"); + r_grid = core::Cvar::get("r_grid", "0", core::Cvar::Archive); r_grid->set_info("[bool] render the space grid"); diff --git a/src/render/render.h b/src/render/render.h index 54205bc..a453464 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -48,6 +48,8 @@ namespace render { extern core::Cvar *r_sky; /// render wireframe models extern core::Cvar *r_wireframe; + /// render vertex normals + extern core::Cvar *r_normals; /// render collision extern core::Cvar *r_collision; /// use hardware generated mipmaps (requires OpenGL 1.4, does not work on all cards) -- cgit v1.2.3