Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2008-03-03 17:39:02 +0000
committerStijn Buys <ingar@osirion.org>2008-03-03 17:39:02 +0000
commitb0af6f8e14449e8bd49efe94da1041628a549120 (patch)
treeaea4b9f1930af1b89e96d05832bc8559fae0a7f0 /src/render
parente379b1bfeb231716e07f0e4ae9ef024be9bfd08f (diff)
usable models, target_engine
Diffstat (limited to 'src/render')
-rw-r--r--src/render/face.cc13
-rw-r--r--src/render/face.h6
-rw-r--r--src/render/model.cc280
-rw-r--r--src/render/model.h56
-rw-r--r--src/render/render.cc8
5 files changed, 220 insertions, 143 deletions
diff --git a/src/render/face.cc b/src/render/face.cc
index cd69b4e..764c452 100644
--- a/src/render/face.cc
+++ b/src/render/face.cc
@@ -9,10 +9,15 @@
namespace render {
-Face::Face(math::Vector3f const & normal) :
+Face::Face(math::Vector3f const & normal, math::Color const *color) :
face_normal(normal)
{
face_normal.normalize();
+
+ if (color)
+ face_color = new math::Color(*color);
+ else
+ face_color = 0;
}
Face::~Face()
@@ -22,6 +27,9 @@ Face::~Face()
}
face_vertex.clear();
+
+ if (face_color)
+ delete face_color;
}
void Face::add_vertex(math::Vector3f const & vertex)
@@ -33,7 +41,8 @@ void Face::add_vertex(math::Vector3f const & vertex)
void Face::draw()
{
- gl::begin(gl::LineLoop);
+ //gl::begin(gl::LineLoop);
+ gl::begin(gl::Polygon);
for (std::vector<math::Vector3f *>::iterator it = face_vertex.begin(); it != face_vertex.end(); it++) {
gl::vertex(*(*it));
}
diff --git a/src/render/face.h b/src/render/face.h
index d44b1d0..a0a4d5a 100644
--- a/src/render/face.h
+++ b/src/render/face.h
@@ -16,12 +16,15 @@ namespace render {
/// one face (polygon) of a model
class Face {
public:
- Face(math::Vector3f const & normal);
+ Face(math::Vector3f const & normal, math::Color const *color=0);
~Face();
/// the normal of this face
inline math::Vector3f const & normal() const { return face_normal; };
+ /// the color of this face
+ inline math::Color const *color() const { return face_color; };
+
/// add a vertex to the face
void add_vertex(math::Vector3f const &vertex);
@@ -30,6 +33,7 @@ public:
private:
math::Vector3f face_normal;
+ math::Color *face_color;
std::vector<math::Vector3f *> face_vertex;
};
diff --git a/src/render/model.cc b/src/render/model.cc
index 907958a..70b5f18 100644
--- a/src/render/model.cc
+++ b/src/render/model.cc
@@ -1,7 +1,7 @@
/*
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
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
*/
#include <iostream>
@@ -23,57 +23,55 @@ const float MAX_BOUNDS = 8192;
const float delta = 10e-10;
Engine::Engine(math::Vector3f const & location) :
- engine_location(location)
-{
-}
+ engine_location(location)
+{}
Engine::~Engine()
-{
-}
+{}
std::map<std::string, Model*> Model::registry;
Model::Model(std::string const & name) :
- model_name(name)
+ model_name(name)
{
model_scale = 1.0f / 1024.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;
}
-
+
// --------- the actual reading
using math::Vector3f;
using math::Plane3f;
-
+
std::vector<Plane3f *> planes;
unsigned int level = 0;
char data[1024];
-
+
std::string class_name;
math::Vector3f class_origin;
float class_angle;
-
+
while (ifs) {
ifs.getline(data, 1023);
std::istringstream linestream(data);
std::string firstword;
-
+
if (linestream >> firstword) {
if (firstword == "//") {
//cout << " COMMENT!" << std::endl;
@@ -85,24 +83,24 @@ Model::Model(std::string const & name) :
//cout << " LEVEL -" << level << std::endl;
if ((level == 2) && (class_name == "worldspawn")) {
//cout << "brush with " << planes.size() << " faces" << std::endl;
-
+
// for every face
std::vector<Vector3f *>points;
for (std::vector<Plane3f *>::iterator face = planes.begin(); face != planes.end(); face++) {
make_face((*face), planes);
}
-
+
// clean planes
for (std::vector<Plane3f *>::iterator it = planes.begin(); it != planes.end(); it++) {
- delete (*it);
+ delete(*it);
}
planes.clear();
-
+
} else if ((level == 1) && (class_name == "target_engine")) {
//con_debug << " engine at " << class_origin << "\n";
add_engine(new Engine(class_origin * model_scale));
}
-
+
if (level == 1) {
class_angle = 0;
class_name.clear();
@@ -110,7 +108,7 @@ Model::Model(std::string const & name) :
}
level--;
-
+
} else if (firstword == "\"classname\"") {
class_name.clear();
if (linestream >> class_name) {
@@ -128,20 +126,20 @@ Model::Model(std::string const & name) :
} else if (firstword == "\"origin\"") {
std::string tmp;
char c;
- while ( (linestream.get(c)) && (c != '"'));
- while ( (linestream.get(c)) && (c != '"'))
+ while ((linestream.get(c)) && (c != '"'));
+ while ((linestream.get(c)) && (c != '"'))
tmp += c;
std::istringstream is(tmp);
is >> class_origin.x;
is >> class_origin.y;
is >> class_origin.z;
//con_debug << " origin '" << class_origin << "'" << std::endl;
-
+
} else if (firstword == "\"angle\"") {
std::string tmp;
char c;
- while ( (linestream.get(c)) && (c != '"'));
- while ( (linestream.get(c)) && (c != '"'))
+ while ((linestream.get(c)) && (c != '"'));
+ while ((linestream.get(c)) && (c != '"'))
tmp += c;
std::istringstream is(tmp);
is >> class_angle;
@@ -164,22 +162,23 @@ Model::Model(std::string const & name) :
linestream >> p3;
linestream >> tmp; // )
linestream >> texture;
-
+
//cout << data << std::endl;
//cout << "(" << p1 << ") (" << p2 << ") (" << p3 << ") " << texture << std::endl;
-
+
Plane3f *plane = new Plane3f(p1, p2, p3);
+ plane->texture() = texture;
planes.push_back(plane);
//cout << "normal " << plane->normal() << std::endl;
} else {
//cout << " UNKNOWN line for '" << classname << "' level " << level << std::endl;
}
- }
+ }
}
}
-
+
ifs.close();
-
+
con_debug << " maps/" << name << ".map " << model_face.size() << " polygons\n";
}
@@ -187,13 +186,13 @@ Model::~Model()
{
// delete all faces
for (std::list<Face *>::iterator fit = model_face.begin(); fit != model_face.end(); fit++) {
- delete (*fit);
+ delete(*fit);
}
model_face.clear();
-
+
// delete all engines
- for(std::list<Engine *>::iterator eit = model_engine.begin(); eit != model_engine.end(); eit++) {
- delete (*eit);
+ for (std::list<Engine *>::iterator eit = model_engine.begin(); eit != model_engine.end(); eit++) {
+ delete(*eit);
}
model_engine.clear();
}
@@ -202,16 +201,24 @@ void Model::make_face(math::Plane3f *face, std::vector<math::Plane3f *> & planes
{
using math::Vector3f;
using math::Plane3f;
-
+
+ // ignore caulk
+ if (face->texture() == "common/caulk") {
+ return;
+ }
+
+ // using suggestions from
+ // http://www.flipcode.com/archives/Level_Editing.shtml
+
//cout << "Face with normal " << face->normal() << endl;
std::vector<math::Vector3f *> 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)) ) {
+
+ // 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;
-
+
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));
@@ -225,38 +232,38 @@ void Model::make_face(math::Plane3f *face, std::vector<math::Plane3f *> & planes
}
// calculate the x coordinate of each face vertex
for (std::vector<Vector3f *>::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;
+ (*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)) ) {
+
+ // 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;
-
+
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));
- vl.push_back(new Vector3f(MAX_BOUNDS, 0, MAX_BOUNDS));
- vl.push_back(new Vector3f(MAX_BOUNDS, 0, -MAX_BOUNDS));
- } else {
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));
+ } else {
+ 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<Vector3f *>::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;
+ (*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;
@@ -271,42 +278,40 @@ void Model::make_face(math::Plane3f *face, std::vector<math::Plane3f *> & planes
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<Vector3f *>::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;
+ (*it)->z = (-face->d() -
+ face->normal().x * (*it)->x -
+ face->normal().y * (*it)->y) /
+ face->normal().z;
}
}
-
- // intersect the face with every plane
+
+ // intersect the face with every plane
for (std::vector<Plane3f *>::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) ) {
+ 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;
@@ -314,7 +319,7 @@ void Model::make_face(math::Plane3f *face, std::vector<math::Plane3f *> & planes
} else {
next = *vl.front();
}
-
+
Vector3f prev;
if (i > 0) {
//cout << " -- at " << i-1 << std::endl;
@@ -322,65 +327,65 @@ void Model::make_face(math::Plane3f *face, std::vector<math::Plane3f *> & planes
} 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.z*plane->normal().z +plane->d()) < delta ) {
-
+ if ((v.x*plane->normal().x + v.y*plane->normal().y + v.z*plane->normal().z +plane->d()) < delta) {
+
// find current
std::vector<Vector3f *>::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.z*plane->normal().z + plane->d()) > -delta ) {
-
+ if ((prev.x*plane->normal().x + 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);
+ 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;
+ (*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.z*plane->normal().z + plane->d()) > -delta ) {
+ if ((next.x*plane->normal().x + next.y*plane->normal().y + next.z*plane->normal().z + plane->d()) > -delta) {
// calculate intersection
-
+
// 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 +
- plane->normal().y * next.y - plane->normal().y * v.y +
- plane->normal().z * next.z - plane->normal().z * v.z);
+ float t2 = (plane->normal().x * next.x - plane->normal().x * v.x +
+ plane->normal().y * next.y - plane->normal().y * v.y +
+ plane->normal().z * next.z - plane->normal().z * v.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] = v [j] + t1 * ( next[j] - v[j]) / t2;
+ (*s)[j] = v [j] + t1 * (next[j] - v[j]) / t2;
}
-
+
//cout << " added " << *s << std::endl;
vit = vl.insert(vit,s);
vit++;
i++;
}
-
+
// erase
delete *vit;
vl.erase(vit);
@@ -391,26 +396,45 @@ void Model::make_face(math::Plane3f *face, std::vector<math::Plane3f *> & planes
}
if (vl.size() > 2) {
+
+ math::Color *color = 0;
+ if (face->texture() == "colors/white") {
+ color = new math::Color(1, 1, 1);
+ } else if (face->texture() == "colors/grey90") {
+ color = new math::Color(0.9, 0.9, 0.9);
+ } else if (face->texture() == "colors/grey75") {
+ color = new math::Color(0.75, 0.75, 0.75);
+ } else if (face->texture() == "colors/grey50") {
+ color = new math::Color(0.5, 0.5, 0.5);
+ } else if (face->texture() == "colors/grey25") {
+ color = new math::Color(0.25, 0.25, 0.25);
+ } else if (face->texture() == "colors/black") {
+ color = new math::Color(0, 0, 0);
+ } else if (face->texture() == "common/entity") {
+ color = 0;
+ }
+
Vector3f n = face->normal();
n.normalize();
- Face *mf = new Face(n);
+ Face *mf = new Face(n, color);
+ if (color) delete color;
for (std::vector<Vector3f *>::iterator it = vl.begin(); it != vl.end(); it++) {
mf->add_vertex(*(*it) * model_scale);
}
-
+
//con_debug << "adding face\n";
add_face(mf);
} else {
con_debug << "Unresolved face!\n";
}
-
+
for (std::vector<Vector3f *>::iterator it = vl.begin(); it != vl.end(); it++) {
- delete (*it);
+ delete(*it);
}
-
+
vl.clear();
-
+
}
void Model::add_face(Face *face)
@@ -423,31 +447,46 @@ void Model::add_engine(Engine *engine)
model_engine.push_back(engine);
}
-void Model::draw(core::Entity const * entity)
+void Model::draw(core::Entity const * entity, math::Vector3f const & eye)
{
//gl::scale(model_scale, model_scale, model_scale);
- render::gl::color(entity->color());
-
+
+ // calculate a normal from eye to entity location
+ math::Vector3f n = entity->location() - eye;
+ n.normalize();
+
// draw all faces
for (std::list<Face *>::iterator fit = model_face.begin(); fit != model_face.end(); fit++) {
+ // poor man's lighting
+ // set the face color depending on the viewing direction
+ float d = fabsf(math::dotproduct(n, (*fit)->normal()));
+
+ if (d > 1)
+ d = 1;
+ d = 0.5f + d/2;
+
+ if ((*fit)->color()) {
+ render::gl::color(*(*fit)->color() * d);
+ } else {
+ render::gl::color(entity->color() * d);
+ }
(*fit)->draw();
}
}
-void Model::draw(core::EntityControlable const * entity)
+void Model::draw(core::EntityControlable const * entity, math::Vector3f const & eye)
{
// draw the model
- draw((core::Entity *) entity);
-
+ draw((core::Entity *) entity, eye);
+
// draw engines
// all engines are assumed to point to the rear
- if(model_engine.size() && entity->thrust()) {
-
- gl::color(1.0f,0 ,0 );
+ if (model_engine.size() && entity->thrust()) {
+
+ gl::color(1.0f,0 ,0);
gl::begin(gl::Lines);
- for(std::list<Engine *>::iterator eit = model_engine.begin(); eit != model_engine.end(); eit++)
- {
+ for (std::list<Engine *>::iterator eit = model_engine.begin(); eit != model_engine.end(); eit++) {
math::Vector3f const & v = (*eit)->location();
gl::vertex(v);
gl::vertex(v.x - 0.0625f*entity->thrust(), v.y, v.z);
@@ -479,9 +518,16 @@ void Model::clear()
{
// delete all models in the registry
for (std::map<std::string, Model*>::iterator mit = registry.begin(); mit != registry.end(); mit++) {
- delete (*mit).second;
+ delete(*mit).second;
}
registry.clear();
}
+void Model::list()
+{
+ for (std::map<std::string, Model*>::iterator mit = registry.begin(); mit != registry.end(); mit++) {
+ con_print << " " << (*mit).second->model_name << " " << (*mit).second->model_face.size() << " polys\n";
+ }
+ con_print << registry.size() << " registered models" << std::endl;
+}
}
diff --git a/src/render/model.h b/src/render/model.h
index dfde809..eca896b 100644
--- a/src/render/model.h
+++ b/src/render/model.h
@@ -1,7 +1,7 @@
/*
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
+ 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__
@@ -14,7 +14,8 @@
#include "core/entity.h"
#include "render/face.h"
-namespace render {
+namespace render
+{
/// a spacecraft engine
class Engine
@@ -22,9 +23,12 @@ class Engine
public:
Engine(math::Vector3f const & location);
~Engine();
-
- inline math::Vector3f const & location() const { return engine_location; }
-
+
+ inline math::Vector3f const & location() const
+ {
+ return engine_location;
+ }
+
private:
math::Vector3f engine_location;
};
@@ -36,45 +40,51 @@ 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; }
-
+ inline std::string const & name() const
+ {
+ return model_name;
+ }
+
/// the Model registry
static std::map<std::string, Model*> registry;
-
+
/// draw the model for an entity
/** This will not draw attached engines, turrents and cannons
*/
- void draw(core::Entity const * entity);
-
+ void draw(core::Entity const * entity, math::Vector3f const & eye);
+
/// draw the model for a controlable enity
/** This will draw all attached engines, turrents and cannons
*/
- void draw(core::EntityControlable const * entity);
-
-/* ---- static functions for the Model registry -------------------- */
-
+ void draw(core::EntityControlable const * entity, math::Vector3f const & eye);
+
+ /* ---- 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
+
+ /// clear the model registry
static void clear();
-
+
+ /// list the content of the model registry
+ static void list();
+
private:
void make_face(math::Plane3f *face, std::vector<math::Plane3f *> & planes);
void add_engine(Engine *engine);
void add_face(Face *face);
-
+
std::list<Face *> model_face;
std::list<Engine *> model_engine;
std::string model_name;
-
+
float model_scale;
-
+
};
}
diff --git a/src/render/render.cc b/src/render/render.cc
index 87f7424..a1a66f9 100644
--- a/src/render/render.cc
+++ b/src/render/render.cc
@@ -14,6 +14,12 @@ namespace render {
GLuint textures[32];
+void func_list_model(std::string const &args)
+{
+ Model::list();
+}
+
+
void init()
{
con_print << "Initializing renderer..." << std::endl;
@@ -34,6 +40,7 @@ void init()
}
Model::clear();
+ core::Func::add("list_model", (core::FuncPtr) func_list_model);
}
void shutdown()
@@ -41,6 +48,7 @@ void shutdown()
con_print << "Shutting down renderer..." << std::endl;
Model::clear();
+ core::Func::remove("list_model");
}
}