From 81787e9004377016236865e95b95707ed6cf1d0b Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 2 Mar 2008 12:23:48 +0000 Subject: initial (buggy) support for .map models --- src/client/draw.cc | 28 ++-- src/core/entity.cc | 13 +- src/core/entity.h | 4 + src/core/gameinterface.cc | 2 +- src/game/game.cc | 4 +- src/math/Makefile.am | 4 +- src/math/mathlib.h | 3 +- src/math/plane3f.cc | 32 ++++ src/math/plane3f.h | 50 ++++++ src/math/vector3f.cc | 19 ++- src/math/vector3f.h | 2 +- src/render/Makefile.am | 5 +- src/render/face.cc | 43 ++++++ src/render/face.h | 39 +++++ src/render/model.cc | 386 ++++++++++++++++++++++++++++++++++++++++++++++ src/render/model.h | 61 ++++++++ src/render/render.cc | 5 + 17 files changed, 669 insertions(+), 31 deletions(-) create mode 100644 src/math/plane3f.cc create mode 100644 src/math/plane3f.h create mode 100644 src/render/face.cc create mode 100644 src/render/face.h create mode 100644 src/render/model.cc create mode 100644 src/render/model.h (limited to 'src') diff --git a/src/client/draw.cc b/src/client/draw.cc index 11d4aa7..76c55b3 100644 --- a/src/client/draw.cc +++ b/src/client/draw.cc @@ -8,6 +8,7 @@ #include "render/render.h" #include "render/sphere.h" #include "render/box.h" +#include "render/model.h" #include "client/client.h" #include "client/camera.h" #include "client/draw.h" @@ -55,23 +56,32 @@ void draw_entity_diamond(core::Entity *entity) // draw an entity of entity_type core::Entity::Default void draw_entity_default(core::Entity *entity) { + render::Model *model = 0; + if (entity->modelname().size()) + model = render::Model::get(entity->modelname()); + render::gl::push(); render::gl::translate(entity->location()); - - switch(entity->shape()) { - case core::Entity::Sphere: - draw_entity_sphere(entity); - break; - case core::Entity::Diamond: - draw_entity_diamond(entity); - break; + if (model) { + render::gl::color(entity->color()); + model->draw(); + } else { + switch(entity->shape()) { + case core::Entity::Sphere: + draw_entity_sphere(entity); + break; + + case core::Entity::Diamond: + draw_entity_diamond(entity); + break; - case core::Entity::Cube: + case core::Entity::Cube: default: draw_entity_cube(entity); break; + } } render::gl::pop(); diff --git a/src/core/entity.cc b/src/core/entity.cc index a0da4ea..2fe381b 100644 --- a/src/core/entity.cc +++ b/src/core/entity.cc @@ -113,15 +113,19 @@ Entity::Entity(std::istream & is) is >> s; // shape is >> entity_radius; is >> entity_direction; + entity_shape = (Shape) s ; char c; while ( (is.get(c)) && (c != '"')); while ( (is.get(c)) && (c != '"')) - n += c; - - entity_shape = (Shape) s ; + n += c; entity_name = n; + while ( (is.get(c)) && (c != '"')); + while ( (is.get(c)) && (c != '"')) + n += c; + entity_modelname = n; + entity_created = true; entity_destroyed = false; entity_dirty = false; @@ -144,7 +148,8 @@ void Entity::serialize(std::ostream & os) const << entity_shape << " " << entity_radius << " " << entity_direction << " " - << "\"" << entity_name << "\""; + << "\"" << entity_name << "\" " + << "\"" << entity_modelname << "\""; } void Entity::serialize_client_update(std::ostream & os) const diff --git a/src/core/entity.h b/src/core/entity.h index 9c90ef9..d887bc1 100644 --- a/src/core/entity.h +++ b/src/core/entity.h @@ -61,6 +61,9 @@ public: /// entity name (can not contain double qoutes ") inline std::string const & name() { return entity_name; } + /// entity model name + inline std::string const & modelname() { return entity_modelname; } + /// dirty flag inline bool dirty() const { return entity_dirty; } @@ -123,6 +126,7 @@ public: /* entity_ variables can be set by the module */ float entity_radius; std::string entity_name; + std::string entity_modelname; Shape entity_shape; math::Vector3f entity_location; math::Color entity_color; diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc index 6f6a4ac..9aa50fc 100644 --- a/src/core/gameinterface.cc +++ b/src/core/gameinterface.cc @@ -64,7 +64,7 @@ GameInterface::~GameInterface() // clear all game related objects void GameInterface::clear() { - con_debug << "Clearing game data\n"; + //con_debug << "Clearing game data\n"; // remove all entities for (std::map::iterator it = Entity::registry.begin(); it != Entity::registry.end(); it++) { diff --git a/src/game/game.cc b/src/game/game.cc index 85cd457..5157270 100644 --- a/src/game/game.cc +++ b/src/game/game.cc @@ -84,6 +84,7 @@ void Game::init() cube->entity_color = Color(0.0f, 0.8f, 0.0f); cube->entity_location = Vector3f(24.0f, 0.0f, -24.0f); cube->entity_name ="cube: Borg cube green"; + cube->entity_modelname = "cube"; cube->entity_moduletypeid = cube_enttype; // the red cube @@ -91,7 +92,8 @@ void Game::init() cube->entity_shape = core::Entity::Cube; cube->entity_color = Color(1.0f, 0.0f, 0.0f); cube->entity_location = Vector3f(16.0f, 0.0f, -16.0f); - cube->entity_name ="cube: Borg cube red"; + cube->entity_name = "cube: Borg cube red"; + cube->entity_modelname = "cube"; cube->entity_moduletypeid = cube_enttype; // the yellow sphere diff --git a/src/math/Makefile.am b/src/math/Makefile.am index c1f1f88..a622ba7 100644 --- a/src/math/Makefile.am +++ b/src/math/Makefile.am @@ -1,9 +1,9 @@ METASOURCES = AUTO -libmath_la_SOURCES = color.cc functions.cc vector3f.cc +libmath_la_SOURCES = color.cc functions.cc plane3f.cc vector3f.cc libmath_la_LDFLAGS = -avoid-version -no-undefined -lm noinst_LTLIBRARIES = libmath.la -noinst_HEADERS = color.h functions.h mathlib.h vector3f.h +noinst_HEADERS = color.h functions.h mathlib.h plane3f.h vector3f.h INCLUDES = -I$(top_srcdir)/src diff --git a/src/math/mathlib.h b/src/math/mathlib.h index ca5b7f4..b76c562 100644 --- a/src/math/mathlib.h +++ b/src/math/mathlib.h @@ -1,5 +1,5 @@ /* - math/math.h + math/mathlib.h This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ @@ -13,6 +13,7 @@ namespace math {} #include "math/vector3f.h" +#include "math/plane3f.h" #include "math/color.h" #include "math/functions.h" diff --git a/src/math/plane3f.cc b/src/math/plane3f.cc new file mode 100644 index 0000000..232bc98 --- /dev/null +++ b/src/math/plane3f.cc @@ -0,0 +1,32 @@ +/* + math/plane3f.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "math/plane3f.h" +#include + +namespace math +{ + +Plane3f::Plane3f(Vector3f const & point0, Vector3f const &point1, Vector3f const &point2) +{ + 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]) ); + pd = -1 * (plane_normal.x * plane_point[0].x + plane_normal.y * plane_point[0].y + plane_normal.z * plane_point[0].z); +} + +Plane3f::Plane3f(Plane3f const & other) +{ + 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]) ); + 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/math/plane3f.h b/src/math/plane3f.h new file mode 100644 index 0000000..ddaef16 --- /dev/null +++ b/src/math/plane3f.h @@ -0,0 +1,50 @@ +/* + math/plane3f.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_MATH_PLANE3F_H__ +#define __INCLUDED_MATH_PLANE3F_H__ + +#include "math/vector3f.h" + +namespace math +{ + +/** @brief A class representing a plane in 3d space + * all points p(x, y, z) on the plane satisfy the general equation + * x*a() + y*b() + z*c() + d() = 0 + */ +class Plane3f +{ +public: + /// a plane defined by 3 points in space + Plane3f(Vector3f const & point0, Vector3f const &point1, Vector3f const &point2); + /// copy constructor + Plane3f(Plane3f const & other); + + /// normal of the plane, not normalized to lenght 1 + inline Vector3f const & normal() const { return plane_normal; } + /// the points defining the plane. + /// @param i 0 <= i < 3 + inline Vector3f const & point(size_t i) const { return plane_point[i]; } + + /// first parameter of the general equation + inline float a() const { return plane_normal[0]; } + /// second parameter of the general equation + inline float b() const { return plane_normal[1]; } + /// third param of the general equation + inline float c() const { return plane_normal[2]; } + /// fourth parameter of the general equation + inline float d() const { return pd; } + +private: + Vector3f plane_point[3]; + Vector3f plane_normal; + float pd; +}; + +} + +#endif // __INCLUDED_MATH_PLANE3F_H__ diff --git a/src/math/vector3f.cc b/src/math/vector3f.cc index ddf46af..371ada1 100644 --- a/src/math/vector3f.cc +++ b/src/math/vector3f.cc @@ -141,15 +141,6 @@ Vector3f operator*(float scalar, const Vector3f& vector) return vector * scalar; } -Vector3f crossproduct(const Vector3f& first, const Vector3f& second) -{ - float x = first[1]*second[2] - first[2]*second[1]; - float y = first[2]*second[0] - first[0]*second[2]; - float z = first[0]*second[1] - first[1]*second[0]; - - return(Vector3f(x,y,z)); -} - std::ostream &operator<<(std::ostream & os, Vector3f const & vector) { os << vector[0] << " " << vector[1] << " " << vector[2]; @@ -163,6 +154,15 @@ std::istream &operator>>(std::istream & is, Vector3f & vector) return is; } +const Vector3f crossproduct(Vector3f const & first, Vector3f const& second) +{ + float x = first[1]*second[2] - first[2]*second[1]; + float y = first[2]*second[0] - first[0]*second[2]; + float z = first[0]*second[1] - first[1]*second[0]; + + return(Vector3f(x,y,z)); +} + float dotproduct(const Vector3f& first, const Vector3f& second) { float r = 0; @@ -170,5 +170,4 @@ float dotproduct(const Vector3f& first, const Vector3f& second) r += first[i] * second[i]; return (r); } - } // namespace math diff --git a/src/math/vector3f.h b/src/math/vector3f.h index d338f50..c2ebc6a 100644 --- a/src/math/vector3f.h +++ b/src/math/vector3f.h @@ -143,7 +143,7 @@ std::istream &operator>>(std::istream & is, Vector3f & vector); Vector3f operator*(float scalar, const Vector3f& vector); /// vector cross product -const Vector3f crossproduct(Vector3f const& first, Vector3f const second); +const Vector3f crossproduct(Vector3f const & first, Vector3f const & second); /// vetor dot product float dotproduct(const Vector3f& first, const Vector3f& second); diff --git a/src/render/Makefile.am b/src/render/Makefile.am index 183ab41..656ae26 100644 --- a/src/render/Makefile.am +++ b/src/render/Makefile.am @@ -3,5 +3,6 @@ METASOURCES = AUTO noinst_LTLIBRARIES = librender.la librender_la_LDFLAGS = -avoid-version -no-undefined @GL_LIBS@ librender_la_LIBADD = $(top_builddir)/src/math/libmath.la -librender_la_SOURCES = box.cc gl.cc render.cc sphere.cc text.cc tga.cc -noinst_HEADERS = box.h gl.h render.h sphere.h text.h tga.h +librender_la_SOURCES = box.cc face.cc gl.cc model.cc render.cc sphere.cc \ + text.cc tga.cc +noinst_HEADERS = box.h face.h gl.h model.h render.h sphere.h text.h tga.h diff --git a/src/render/face.cc b/src/render/face.cc new file mode 100644 index 0000000..cd69b4e --- /dev/null +++ b/src/render/face.cc @@ -0,0 +1,43 @@ +/* + render/face.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "render/face.h" +#include "render/gl.h" + +namespace render { + +Face::Face(math::Vector3f const & normal) : + face_normal(normal) +{ + face_normal.normalize(); +} + +Face::~Face() +{ + for (std::vector::iterator it = face_vertex.begin(); it != face_vertex.end(); it++) { + delete (*it); + } + + face_vertex.clear(); +} + +void Face::add_vertex(math::Vector3f const & vertex) +{ + math::Vector3f *v = new math::Vector3f(vertex); + + face_vertex.push_back(v); +} + +void Face::draw() +{ + gl::begin(gl::LineLoop); + for (std::vector::iterator it = face_vertex.begin(); it != face_vertex.end(); it++) { + gl::vertex(*(*it)); + } + gl::end(); +} + +} diff --git a/src/render/face.h b/src/render/face.h new file mode 100644 index 0000000..d44b1d0 --- /dev/null +++ b/src/render/face.h @@ -0,0 +1,39 @@ +/* + render/face.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_RENDER_FACE_H__ +#define __INCLUDED_RENDER_FACE_H__ + +#include + +#include "math/mathlib.h" + +namespace render { + +/// one face (polygon) of a model +class Face { +public: + Face(math::Vector3f const & normal); + ~Face(); + + /// the normal of this face + inline math::Vector3f const & normal() const { return face_normal; }; + + /// add a vertex to the face + void add_vertex(math::Vector3f const &vertex); + + /// draw the polygon + void draw(); + +private: + math::Vector3f face_normal; + std::vector face_vertex; +}; + +} + +#endif // __INCLUDED_RENDER_FACE_H__ + diff --git a/src/render/model.cc b/src/render/model.cc new file mode 100644 index 0000000..f048b7f --- /dev/null +++ b/src/render/model.cc @@ -0,0 +1,386 @@ +/* + render/model.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "render/model.h" +#include "render/gl.h" +#include "filesystem/filesystem.h" + +namespace render +{ + +const float MAX_BOUNDS = 8192; +const float delta = 10e-8; + +std::map Model::registry; + +Model::Model(std::string const & name) : + model_name(name) +{ + model_scale = 1.0f / 64.0f; + + std::string fn("maps/"); + fn.append(name); + fn.append(".map"); + filesystem::File *f = filesystem::open(fn.c_str()); + + if (!f) { + return; + } + + fn = f->path(); + fn.append(f->name()); + filesystem::close(f); + + std::ifstream ifs(fn.c_str()); + if (!ifs.is_open()) { + con_warn << "Could not stream " << fn << "!\n"; + return; + } + con_debug << "Reading " << fn << "\n"; + + // --------- the actual reading + using math::Vector3f; + using math::Plane3f; + + std::vector planes; + std::string classname; + unsigned int level = 0; + char data[1024]; + + while (ifs) { + ifs.getline(data, 1023); + std::istringstream linestream(data); + std::string firstword; + + if (linestream >> firstword) { + if (firstword == "//") { + //cout << " COMMENT!" << std::endl; + continue; + } else if (firstword == "{") { + level ++; + //cout << " LEVEL +" << level << std::endl; + } else if (firstword == "}") { + //cout << " LEVEL -" << level << std::endl; + if ((level == 2) && (classname == "worldspawn")) { + //cout << "brush with " << planes.size() << " faces" << std::endl; + + // for every face + std::vectorpoints; + for (std::vector::iterator face = planes.begin(); face != planes.end(); face++) { + make_face((*face), planes); + } + + // clean planes + for (std::vector::iterator it = planes.begin(); it != planes.end(); it++) { + delete (*it); + } + planes.clear(); + } + level--; + } else if (firstword == "\"classname\"") { + classname.clear(); + if (linestream >> classname) { + if (classname.size() > 2) { + classname.erase(0,1); + classname.erase(classname.size()-1, 1); + linestream >> classname; + //cout << " CLASS '" << classname << "'" << std::endl; + } else + classname.clear(); + } else { + //cout << " EMPTY CLASS" << std::endl; + } + } else if (firstword == "(") { + if ((level == 2) && (classname == "worldspawn")) { + //cout << " BRUSH PLANE" << std::endl; + Vector3f p1; + Vector3f p2; + Vector3f p3; + std::string tmp; + std::string texture; + + linestream >> p1; + linestream >> tmp; // ) + linestream >> tmp; // ( + linestream >> p2; + linestream >> tmp; // ) + linestream >> tmp; // ( + linestream >> p3; + linestream >> tmp; // ) + linestream >> texture; + + //cout << data << std::endl; + //cout << "(" << p1 << ") (" << p2 << ") (" << p3 << ") " << texture << std::endl; + + Plane3f *plane = new Plane3f(p1, p2, p3); + planes.push_back(plane); + //cout << "normal " << plane->normal() << std::endl; + } else { + //cout << " UNKNOWN line for '" << classname << "' level " << level << std::endl; + } + } + } + } + + ifs.close(); + + con_debug << "Loaded model " << name << " with " << model_face.size() << " polygons\n"; +} + +Model::~Model() +{ + // delete all faces + for (std::list::iterator fit = model_face.begin(); fit != model_face.end(); fit++) { + delete(*fit); + } + + model_face.clear(); +} + +void Model::make_face(math::Plane3f *face, std::vector & planes) +{ + using math::Vector3f; + using math::Plane3f; + + //cout << "Face with normal " << face->normal() << endl; + std::vector vl; + + // inital vertexes + + // 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)) ) { + //cout << " x oriented" << std::endl; + vl.push_back(new math::Vector3f(0, -MAX_BOUNDS, -MAX_BOUNDS)); + vl.push_back(new math::Vector3f(0, -MAX_BOUNDS, MAX_BOUNDS)); + vl.push_back(new math::Vector3f(0, MAX_BOUNDS, MAX_BOUNDS)); + vl.push_back(new math::Vector3f(0, MAX_BOUNDS, -MAX_BOUNDS)); + + // calculate the x coordinate of each face vertex + for (std::vector::iterator it = vl.begin(); it != vl.end(); it++) { + (*it)->x = ( face->d() - + face->normal().z * (*it)->z - + face->normal().y * (*it)->y ) / + face->normal().x; + } + } + + // 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)) ) { + //cout << " y oriented" << std::endl; + vl.push_back(new Vector3f(-MAX_BOUNDS, 0, -MAX_BOUNDS)); + vl.push_back(new Vector3f(-MAX_BOUNDS, 0, MAX_BOUNDS)); + vl.push_back(new Vector3f(MAX_BOUNDS, 0, MAX_BOUNDS)); + vl.push_back(new Vector3f(MAX_BOUNDS, 0, -MAX_BOUNDS)); + + // calculate the x coordinate of each face vertex + for (std::vector::iterator it = vl.begin(); it != vl.end(); it++) { + (*it)->y = ( face->d() - + face->normal().z * (*it)->z - + face->normal().x * (*it)->x ) / + face->normal().y; + } + } + + // face must be z-axis oriented + else { + //cout << " z oriented" << std::endl; + vl.push_back(new Vector3f(-MAX_BOUNDS, -MAX_BOUNDS, 0)); + vl.push_back(new Vector3f(-MAX_BOUNDS, MAX_BOUNDS, 0)); + vl.push_back(new Vector3f(MAX_BOUNDS, MAX_BOUNDS, 0)); + vl.push_back(new Vector3f(MAX_BOUNDS, -MAX_BOUNDS, 0)); + + // calculate the x coordinate of each face vertex + for (std::vector::iterator it = vl.begin(); it != vl.end(); it++) { + (*it)->z = ( face->d() - + face->normal().x * (*it)->x - + face->normal().y * (*it)->y ) / + face->normal().z; + } + } + + + // intersect the face with every plane + for (std::vector::iterator pit = planes.begin(); pit != planes.end(); pit++) { + Plane3f *plane = (*pit); + if (plane == face) { + continue; + } + + Vector3f fn = crossproduct(face->point(1)-face->point(0), face->point(2)-face->point(0)); + Vector3f pn = crossproduct(plane->point(1)-plane->point(0), plane->point(2)-plane->point(0)); + + Vector3f t = crossproduct(fn, pn); + if (t.x == 0 && t.y ==0 && t.z == 0) { + continue; + } + + //cout << " intersecting with plane with normal " << plane->normal() << std::endl; + // using suggestions from + // http://www.flipcode.com/archives/Level_Editing.shtml + + // intersect face with plane + for (int i=0; vl.size() - i > 0; i++) { + + Vector3f v(*vl.at(i)); + + + Vector3f next; + if (vl.size() - i > 1) { + //cout << " -- at " << i+1 << std::endl; + next = *vl.at(i+1); + } else { + next = *vl.front(); + } + + Vector3f prev; + if (i > 0) { + //cout << " -- at " << i-1 << std::endl; + prev = *vl.at(i-1); + } else { + prev = *vl.back(); + } + + //cout << " vertex " << i << " prev " << prev << " v " << v << " next " << next << std::endl; + if ((v.x*plane->normal().x + v.y*plane->normal().y + v.y*plane->normal().y + v.z*plane->normal().z +plane->d()) < -delta ) { + + // find current + std::vector::iterator vit = vl.begin(); + while ((*vit) != vl.at(i)) { + vit++; + } + + // check if prev - v intersects with plane + if ((prev.x*plane->normal().x + prev.y*plane->normal().y + prev.y*plane->normal().y + prev.z*plane->normal().z + plane->d()) > delta ) { + + // calculate intersection + float t1 = -plane->normal().x * prev.x - plane->normal().y * prev.y - plane->normal().z * prev.z -plane->d(); + 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); + //cout << "prev t2 " << t2 << std::endl; + Vector3f *s = new Vector3f; + + if (t2 == 0) { + *s = v; + } else { + for (int j = 0; j < 3; j++) + (*s)[j] = prev [j] + t1 * ( v[j] - prev[j]) / t2; + } + + //cout << " added " << *s << std::endl; + vit = vl.insert(vit,s); + vit++; + i++; + } + + // check if next - v intersects with plane + if ((next.x*plane->normal().x + next.y*plane->normal().y + next.y*plane->normal().y + next.z*plane->normal().z + plane->d()) > delta ) { + // calculate intersection + + // calculate intersection + float t1 = -plane->normal().x * next.x - plane->normal().y * next.y - plane->normal().z * next.z -plane->d(); + float t2 = (plane->normal().x * v.x - plane->normal().x * next.x + + plane->normal().y * v.y - plane->normal().y * next.y + + plane->normal().z * v.z - plane->normal().z * next.z); + //cout << "next t2 " << t2 << std::endl; + Vector3f *s = new Vector3f; + + if (t2 == 0) { + *s = v; + } else { + for (int j = 0; j < 3; j++) + (*s)[j] = next [j] + t1 * ( v[j] - next[j]) / t2; + } + + //cout << " added " << *s << std::endl; + vit = vl.insert(vit,s); + vit++; + i++; + } + + // erase + delete *vit; + vl.erase(vit); + i--; + } + + } + } + + if (vl.size() > 2) { + Vector3f n = face->normal(); + n.normalize(); + Face *mf = new Face(n); + + for (std::vector::iterator it = vl.begin(); it != vl.end(); it++) { + mf->add_vertex(*(*it)); + } + + //con_debug << "adding face\n"; + add_face(mf); + } + + for (std::vector::iterator it = vl.begin(); it != vl.end(); it++) { + delete (*it); + } + + vl.clear(); + +} + +void Model::add_face(Face *face) +{ + model_face.push_back(face); +} + +void Model::draw() +{ + gl::scale(model_scale, model_scale, model_scale); + + // draw all faces + for (std::list::iterator fit = model_face.begin(); fit != model_face.end(); fit++) { + (*fit)->draw(); + } + +} + +Model *Model::find(std::string const & name) +{ + std::map::iterator it = registry.find(name); + if (it == registry.end()) + return 0; + else + return (*it).second; +} + +Model *Model::get(std::string const & name) +{ + Model *model = find(name); + if (!model) { + model = new Model(name); + registry[model->name()] = model; + } + return model; +} + +void Model::clear() +{ + // delete all models in the registry + for (std::map::iterator mit = registry.begin(); mit != registry.end(); mit++) { + delete (*mit).second; + } + registry.clear(); +} + +} diff --git a/src/render/model.h b/src/render/model.h new file mode 100644 index 0000000..ab6207e --- /dev/null +++ b/src/render/model.h @@ -0,0 +1,61 @@ +/* + render/model.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_RENDER_MODEL_H__ +#define __INCLUDED_RENDER_MODEL_H__ + +#include +#include + +#include "render/face.h" +#include "math/plane3f.h" + +namespace render { + +/// a 3D model contains a list of faces +class Model +{ +public: + /// load a model from disk + Model(std::string const & name); + ~Model(); + + /// the name of the model + inline std::string const & name() const { return model_name; } + + void add_face(Face *face); + + /// the Model registry + static std::map registry; + + /// draw the model + void draw(); + +/* ---- static functions for the Model registry -------------------- */ + + /// get name model, returns 0 if not found + static Model *find(std::string const & name); + + /// get named model from the registry and load it if necessary + static Model *get(std::string const & name); + + /// clear the Model registry + static void clear(); + +private: + void make_face(math::Plane3f *face, std::vector & planes); + + std::list model_face; + std::string model_name; + + float model_scale; + +}; + +} + +#endif // __INCLUDED_RENDER_MODEL_H__ + diff --git a/src/render/render.cc b/src/render/render.cc index fce3b6a..87f7424 100644 --- a/src/render/render.cc +++ b/src/render/render.cc @@ -6,6 +6,7 @@ // project headers #include "render/render.h" +#include "render/model.h" #include "core/core.h" #include "sys/sys.h" @@ -31,11 +32,15 @@ void init() con_error << "Essential file bitmaps/conchars.tga missing" << std::endl; core::application()->shutdown(); } + + Model::clear(); } void shutdown() { con_print << "Shutting down renderer..." << std::endl; + + Model::clear(); } } -- cgit v1.2.3