From 7fef8856b21215b0dd28dcc57f04c8a98ab5226f Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sat, 22 Mar 2008 22:36:39 +0000 Subject: Implemented vertex arrays --- INSTALL | 10 ++ README | 45 ++++-- osirion.kdevelop.pcs | Bin 526697 -> 518254 bytes osirion.kdevses | 8 +- src/client/view.cc | 17 +- src/core/model.cc | 180 +++++++++++++-------- src/core/model.h | 57 ++++--- src/core/netserver.cc | 2 +- src/render/draw.cc | 441 +++++++++++++++++++++++++++++++++----------------- src/render/draw.h | 8 + src/render/render.cc | 4 + src/render/render.h | 2 + src/render/sphere.cc | 9 +- 13 files changed, 522 insertions(+), 261 deletions(-) diff --git a/INSTALL b/INSTALL index 3296e35..285747f 100644 --- a/INSTALL +++ b/INSTALL @@ -105,7 +105,17 @@ Installing gtkradiant 1.5.0 support files (optional) Save the changes. +Source data (optional) + The .xcf and .svg source files used to create the game data + can also be downloaded. Note that you do not need these files + to play the game or to create .map models. You only have to + download them them if you want to create new game graphics. + + To download the source data: + + svn checkout svn://intranifty.no-ip.org/osirion-data-src data-src + Executing To run the client program, execute: diff --git a/README b/README index 570daa5..6610a90 100644 --- a/README +++ b/README @@ -2,15 +2,15 @@ The Osirion Project - README This is the Osirion project. I wrote it to get a better grasp on - game design with opengl and to get some C++ practice. + game design with OpenGL and to get some C++ practice. Maybe someday, it will be a real game. Read INSTALL for instructions on building, installing and udpating. Dedicated server - The dedicated server will accept incoming connections on port 8042. - There is no server console. + By default, the dedicated server will accept incoming connections + on UDP port 8042. There is no server console. Client @@ -79,7 +79,12 @@ Console functions cl_color 1.0 1.0 0.0 connect - Settings are saved when you quit the application. +Configuration + + Variables marked with the 'A' flag will be archived, their value + will be written to the configuration file on exit. The dedicated + server reads its configuration from server.ini, the client + will use client.ini. Organization of the distribution @@ -103,6 +108,7 @@ Organization of the distribution /bitmaps essential bitmaps /ini ini files /maps .map models + /satellites sattelites /ships spaceships /stations space stations /textures textures @@ -111,24 +117,24 @@ Organization of the distribution The game data can be obtained as a seperate distribution. Refer to the file INSTALLATION for more information. -Editing game parameters +Editing game data One of the goals of the Osirion Project, is to create an engine - that makes it very easy to extend the game. At this moment, the - game reads the world description from ini/world.ini and a list of - buyable ships from ini/ships.ini. + that makes it very easy to adapt and extend the game world. + At the moment, the game reads the world description from + ini/world.ini and a list of buyable ships from ini/ships.ini. - I recommend not to edit the original game data, but to make a copy - in your personal osirion folder '~/.osirion'. This directory mimics - the directory structure of the 'data' directory but any file found - in the personal diretory will get precedence over the corresponding - file in the game data directory. + I recommend you do not edit the original game data, but to make a copy + into your personal osirion folder '~/.osirion'. This directory mimics + the directory structure of the 'data' directory and any file found + there will get precedence over the corresponding file in + the game data directory. Adding models The models are basic Quake2 style .map files with custom entities and can be created with a program like gtkradiant. No map compiler is - necessary, the engine reads the files directly. Refer to the file + necessary, the engine reads the .map files directly. Refer to the file INSTALL on how to install the support files for gtkradiant 1.5.0. The textures in the textures/colors/ directory are mapped to RGB colors @@ -141,7 +147,7 @@ Adding models texture will get the current game entity color. This makes it possible to use the current player color on ship models. - Add an info_engine entity to add an engine exhaust to the ship model. + Add an info_engine entity to add an engine exhaust to a ship model. Notes @@ -153,12 +159,19 @@ Notes Project contributors - Thorn[mDc] - Ship models + Thorn[mDc] - Canasta and Sharkan ship models + Alpha testing + Josky=KCT= - Shuttle ship model IRC The official Osirion IRC channel is #osirion on irc.soliter.org +Web + + Screenshots can be found at + http://ingar.soliter.org/screenshots/osirion + Acknowledgements This project could not have been possible without the work of others: diff --git a/osirion.kdevelop.pcs b/osirion.kdevelop.pcs index e58b241..b0fd24b 100644 Binary files a/osirion.kdevelop.pcs and b/osirion.kdevelop.pcs differ diff --git a/osirion.kdevses b/osirion.kdevses index c865c2a..5dd7e63 100644 --- a/osirion.kdevses +++ b/osirion.kdevses @@ -2,11 +2,11 @@ - - + + - - + + diff --git a/src/client/view.cc b/src/client/view.cc index 466723f..5d14992 100644 --- a/src/client/view.cc +++ b/src/client/view.cc @@ -56,7 +56,7 @@ void reset() GLfloat ambient_light[] = { 0.2f, 0.2f, 0.2f, 1.0f }; GLfloat diffuse_light[] = { 0.4f, 0.4f, 0.4f, 1.0f }; GLfloat specular_light[] = { 0.4f, 0.4f, 0.4f, 1.0f }; - GLfloat specular_reflectance[] = { 0.5f, 0.5f, 0.5f, 1.0f }; + GLfloat specular_reflectance[] = { 0.2f, 0.2f, 0.2f, 1.0f }; glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_light); @@ -85,6 +85,8 @@ void reset() // alpha-blending gl::blendfunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl::enable(GL_BLEND); + + // client state } void draw_loader() @@ -130,7 +132,7 @@ void draw_status() int hours = (int) sys::time() / 3600; int minutes = (int)(sys::time() - 3600*hours) / 60; int seconds = (int)(sys::time() - 3600*hours - 60 *minutes); - status << " clock " << std::setfill('0') << std::setw(2) << hours << ":" + status << "clock " << std::setfill('0') << std::setw(2) << hours << ":" << std::setfill('0') << std::setw(2) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; @@ -138,9 +140,18 @@ void draw_status() seconds = (int) floorf(core::application()->time() - (float) minutes* 60.0f); status << " time " << std::setfill('0') << std::setw(2) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; - status << " fps " << std::setw(4) << fps; + draw_text(CHARWIDTH, 4, status); + // print stats if desired + if (render::r_drawstats && render::r_drawstats->value()) { + std::stringstream stats; + stats << "fps " << std::setw(6) << fps << "\n"; + stats << "tris " << std::setw(6) << render::Stats::tris << "\n"; + stats << "spheres " << std::setw(4) << render::Stats::spheres << "\n"; + draw_text(video::width-CHARWIDTH*13, CHARHEIGHT*3, stats); + } + // print the version number in the upper right corner gl::color(0.0f, 1.0f, 0.0f, 1.0f); std::string version("ver. "); diff --git a/src/core/model.cc b/src/core/model.cc index 88a1040..df6e563 100644 --- a/src/core/model.cc +++ b/src/core/model.cc @@ -12,6 +12,7 @@ #include #include +#include "core/cvar.h" #include "core/model.h" #include "filesystem/filesystem.h" @@ -21,6 +22,64 @@ namespace core const float MAX_BOUNDS = 8192; const float delta = 10e-10; +const size_t VERTEXARRAYVERTEXARRAYSIZE=65536*3; + +/* ---------- core::VertexArray ------------------------------------ */ +float VertexArray::vertex[VERTEXARRAYSIZE]; +float VertexArray::vertex_color[VERTEXARRAYSIZE]; +float VertexArray::vertex_normal[VERTEXARRAYSIZE]; + +float VertexArray::evertex[VERTEXARRAYSIZE]; +float VertexArray::evertex_normal[VERTEXARRAYSIZE]; + +size_t VertexArray::vertex_index; +size_t VertexArray::evertex_index; + +void VertexArray::clear() +{ + memset(vertex, 0, sizeof(vertex)); + memset(vertex_color, 0, sizeof(vertex_color)); + memset(vertex_normal, 0, sizeof(vertex_normal)); + + memset(evertex, 0, sizeof(evertex)); + memset(evertex_normal, 0, sizeof(evertex_normal)); + + vertex_index = 0; + evertex_index = 0; +} + +void VertexArray::add_vertex(math::Vector3f const &v, math::Vector3f const &n, math::Color const &color) { + if (vertex_index + 3 >= VERTEXARRAYSIZE) { + con_warn << "VertexArray overflow!" << std::endl; + return; + } + + for (int i = 0; i < 3; i ++) { + 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_index += 3; +} + +void VertexArray::add_evertex(math::Vector3f const &v, math::Vector3f const &n) { + if (evertex_index + 3 >= VERTEXARRAYSIZE) { + con_warn << "EVertexArray overflow!" << std::endl; + return; + } + + for (int i = 0; i < 3; i ++) { + evertex[evertex_index+i] = v[i]; + evertex_normal[evertex_index+i] = n[i]; + } + + evertex_index += 3; +} + /* ---------- core::Light ------------------------------------------ */ Light::Light(math::Vector3f const & location, math::Color const & color) : @@ -40,38 +99,6 @@ Engine::Engine(math::Vector3f const & location) : Engine::~Engine() {} -/* ---------- core::Face ------------------------------------------ */ - -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() -{ - for (std::vector::iterator it = face_vertex.begin(); it != face_vertex.end(); it++) { - delete (*it); - } - - face_vertex.clear(); - - if (face_color) - delete face_color; -} - -void Face::add_vertex(math::Vector3f const & vertex) -{ - math::Vector3f *v = new math::Vector3f(vertex); - - face_vertex.push_back(v); -} - /* ---------- core::Model ------------------------------------------ */ std::map Model::registry; @@ -81,6 +108,10 @@ Model::Model(std::string const & name) : { model_valid = false; model_scale = 1.0f / 1024.0f; + model_first_vertex = 0; + model_first_evertex = 0; + model_vertex_count = 0; + model_evertex_count = 0; std::string fn("maps/"); fn.append(name); @@ -113,6 +144,9 @@ Model::Model(std::string const & name) : math::Vector3f class_origin; float class_angle; math::Color class_color; + + model_first_evertex = VertexArray::evertex_index/3; + model_first_vertex = VertexArray::vertex_index/3; while (ifs) { ifs.getline(data, 1023); @@ -135,14 +169,15 @@ Model::Model(std::string const & name) : } else if (firstword == "}") { //cout << " LEVEL -" << level << std::endl; if ((level == 2) && (class_name == "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); + + if (!(Cvar::sv_dedicated && Cvar::sv_dedicated->value())) { + // 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); @@ -246,7 +281,7 @@ Model::Model(std::string const & name) : ifs.close(); - if (model_face.size()) { + if ((model_vertex_count + model_evertex_count) > 0 ) { if (model_maxbbox.lengthsquared() > model_minbbox.lengthsquared()) { model_radius = model_maxbbox.length(); } else { @@ -254,17 +289,12 @@ Model::Model(std::string const & name) : } model_valid = true; } - con_debug << " maps/" << name << ".map " << model_face.size() << " polygons\n"; + //con_debug << " maps/" << name << ".map " << model_face.size() << " polygons\n"; + con_debug << " maps/" << name << ".map " << (model_vertex_count + model_evertex_count)/3 << " triangles" << std::endl; } Model::~Model() { - // delete all faces - for (std::list::iterator fit = model_face.begin(); fit != model_face.end(); fit++) { - delete(*fit); - } - model_face.clear(); - // delete all engines for (std::list::iterator eit = model_engine.begin(); eit != model_engine.end(); eit++) { delete(*eit); @@ -291,7 +321,6 @@ void Model::make_face(math::Plane3f *face, std::vector & planes // using suggestions from // http://www.flipcode.com/archives/Level_Editing.shtml - //cout << "Face with normal " << face->normal() << endl; std::vector vl; // inital vertexes @@ -496,28 +525,46 @@ void Model::make_face(math::Plane3f *face, std::vector & planes } else color = new math::Color(1.0f, 0.0, 1.0f); - /* + // calculate bounding box + for (std::vector::iterator it = vl.begin(); it != vl.end(); it++) { + + *(*it) *= model_scale; + + for (int i=0; i < 3; i++) { + if (model_maxbbox[i] < (*(*it))[i]) + model_maxbbox[i] = (*(*it))[i]; + + if (model_minbbox[i] > (*(*it))[i]) + model_minbbox[i] = (*(*it))[i]; + } + } + // split face into triangles while (vl.size() >2 ) { std::vector::iterator v0 = vl.begin(); std::vector::reverse_iterator vn = vl.rbegin(); std::vector::reverse_iterator vn1 = vl.rbegin(); ++vn1; - */ - Face *mf = new Face(face->normal()*-1, color); - for (std::vector::iterator it = vl.begin(); it != vl.end(); it++) { - mf->add_vertex(*(*it) * model_scale); - // bounding box - for (int i=0; i < 3; i++) { - if (model_maxbbox[i] < (*(*it))[i] * model_scale) - model_maxbbox[i] = (*(*it))[i] * model_scale; - - if (model_minbbox[i] > (*(*it))[i] * model_scale) - model_minbbox[i] = (*(*it))[i] * model_scale; + Vector3f n(face->normal()*-1); + n.normalize(); + + if (!color) { + VertexArray::add_evertex(*(*vn1), n); + VertexArray::add_evertex(*(*vn), n); + VertexArray::add_evertex(*(*v0), n); + model_evertex_count += 3; + } else { + VertexArray::add_vertex(*(*vn1), n, *color); + VertexArray::add_vertex(*(*vn), n, *color); + VertexArray::add_vertex(*(*v0), n, *color); + model_vertex_count += 3; } + + delete (*vn); + vl.pop_back(); } - add_face(mf); + //add_face(mf); if (color) delete color; } else { con_debug << "Unresolved face!\n"; @@ -531,11 +578,6 @@ void Model::make_face(math::Plane3f *face, std::vector & planes } -void Model::add_face(Face *face) -{ - model_face.push_back(face); -} - void Model::add_engine(Engine *engine) { model_engine.push_back(engine); @@ -572,12 +614,16 @@ void Model::clear() delete(*mit).second; } registry.clear(); + + // clear the vertex array + VertexArray::clear(); } void Model::list() { for (std::map::iterator mit = registry.begin(); mit != registry.end(); mit++) { - con_print << " " << (*mit).second->model_name << " " << (*mit).second->model_face.size() << " polys " + con_print << " " << (*mit).second->name() << " " + << ((*mit).second->vertex_count() + (*mit).second->evertex_count())/3 << " triangles " << (*mit).second->model_engine.size() << " engines " << (*mit).second->model_light.size() << " lights\n"; } diff --git a/src/core/model.h b/src/core/model.h index 00c8a48..5deee35 100644 --- a/src/core/model.h +++ b/src/core/model.h @@ -18,27 +18,31 @@ namespace core { -/// one face (polygon) of a model -class Face { +/// Global vertex array + + +const size_t VERTEXARRAYSIZE=65536*512; + +class VertexArray +{ public: - Face(math::Vector3f const & normal, math::Color const *color=0); - ~Face(); + /// model vertices + static float vertex[VERTEXARRAYSIZE]; + static float vertex_color[VERTEXARRAYSIZE]; + static float vertex_normal[VERTEXARRAYSIZE]; - /// the normal of this face - inline math::Vector3f const & normal() const { return face_normal; }; + /// model vertices with entity color + static float evertex[VERTEXARRAYSIZE]; + static float evertex_normal[VERTEXARRAYSIZE]; - /// the color of this face - inline math::Color const *color() const { return face_color; }; + static size_t vertex_index; + static size_t evertex_index; - /// add a vertex to the face - void add_vertex(math::Vector3f const &vertex); + static void clear(); - /// face vertexes - std::vector face_vertex; + static void add_vertex(math::Vector3f const &v, math::Vector3f const &n, math::Color const &color); + static void add_evertex(math::Vector3f const &v, math::Vector3f const &n); -private: - math::Vector3f face_normal; - math::Color *face_color; }; @@ -95,6 +99,18 @@ public: /// 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 vertexes in this model + inline size_t vertex_count() const { return model_vertex_count; } + + /// first vertex in the global VertexArray + inline size_t first_evertex() const { return model_first_evertex; } + + /// number of vertexes in this model + inline size_t evertex_count() const { return model_evertex_count; } + /// radius inline float radius() const { return model_radius; } @@ -115,19 +131,17 @@ public: /// list the content of the model registry static void list(); - /// list of Faces - std::list model_face; - /// list of Engines std::list model_engine; /// list of Lights std::list model_light; + + private: void make_face(math::Plane3f *face, std::vector & planes); void add_engine(Engine *engine); - void add_face(Face *face); void add_light(Light *light); std::string model_name; @@ -138,6 +152,11 @@ private: math::Vector3f model_maxbbox; math::Vector3f model_minbbox; + + size_t model_first_vertex; + size_t model_vertex_count; + size_t model_first_evertex; + size_t model_evertex_count; }; } diff --git a/src/core/netserver.cc b/src/core/netserver.cc index c8c0a9d..16beee0 100644 --- a/src/core/netserver.cc +++ b/src/core/netserver.cc @@ -284,7 +284,7 @@ void NetServer::broadcast(std::string const & message, Player *ignore_player) } } -// find the client corresponding to a player id +// find the client corresponding to a player NetClient *NetServer::find_client(Player const *player) { for (std::list::iterator it = clients.begin(); it != clients.end(); it++) { diff --git a/src/render/draw.cc b/src/render/draw.cc index 9e1e5ea..77f8457 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -13,6 +13,15 @@ namespace render { +size_t Stats::tris; +size_t Stats::spheres; + +void Stats::clear() +{ + tris = 0; + spheres = 0; +} + Sphere sphere(1); math::Vector3f v0(1, -1, 1); @@ -26,79 +35,19 @@ math::Vector3f v6(-1, 1, -1); math::Vector3f v7(-1, -1, -1); const float drawdistance = 128.0f; +const float drawfxdistance = 32.0f; + math::Vector3f camera_target; float angle = 0; -void draw_model(core::Model *model, core::Entity *entity) -{ - // draw all faces - for (std::list::iterator fit = model->model_face.begin(); fit != model->model_face.end(); fit++) { - if ((*fit)->color()) { - render::gl::color(*(*fit)->color()); - } else { - render::gl::color(entity->color()); - } - - // draw all vertexes - gl::begin(gl::Polygon); - //gl::begin(gl::LineLoop); - gl::normal((*fit)->normal()); - for (std::vector::iterator vit = (*fit)->face_vertex.begin(); vit != (*fit)->face_vertex.end(); vit++) { - gl::vertex(*(*vit)); - } - gl::end(); - } - - if (r_drawradius && r_drawradius->value()) { - sphere.sphere_color = entity->color(); - sphere.sphere_color.a = 0.25f; - sphere.radius = model->radius(); - gl::enable(GL_BLEND); // enable alpha blending again - sphere.draw(); - gl::disable(GL_BLEND); - } -} - -void draw_model_engines(core::Model *model, core::EntityControlable *entity) -{ - if (model->model_engine.size() && entity->thrust()) { - gl::color(1.0f,0 ,0); - gl::begin(gl::Lines); - - for (std::list::iterator eit = model->model_engine.begin(); eit != model->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); - } - gl::end(); - } - -} - -void draw_model_lights(core::Model *model, core::Entity *entity) -{ - if (model->model_light.size()) { - gl::disable(GL_LIGHTING); - glPointSize(10); - gl::begin(gl::Points); - - for (std::list::iterator lit = model->model_light.begin(); lit != model->model_light.end(); lit++) { - math::Vector3f location = (*lit)->location(); - gl::color((*lit)->color()); - gl::vertex(location); - } - - gl::end(); - glPointSize(1); - gl::enable(GL_LIGHTING); - } -} +/* ----- Default Entity shapes ------------------------------------- */ void draw_entity_sphere(core::Entity *entity) { sphere.sphere_color = entity->color(); sphere.radius = entity->radius(); sphere.draw(); + Stats::spheres += 1; } void draw_entity_cube(core::Entity *entity) @@ -170,117 +119,311 @@ void draw_entity_axis(core::Entity *entity) gl::end(); } +/* ----- Entity models --------------------------------------------- */ -// draw an entity of entity_type core::Entity::Default -void draw_entity_default(core::Entity *entity) +void draw_model_vertex(core::Model *model, core::Entity *entity) { - using namespace render; + // draw model vertices + if (model->vertex_count()) { + size_t index = model->first_vertex(); + size_t count = model->vertex_count(); - core::Model *model = 0; - if (entity->modelname().size()) { - model = core::Model::get(entity->modelname()); - } + if (r_drawwireframe && r_drawwireframe->value()) { + glDrawArrays(gl::LineLoop, index, count); + } else { + glDrawArrays(gl::Triangles, index, count); + } - if (model && math::distancesquared(camera_target, entity->location()) > drawdistance*drawdistance*model->radius()) - return; + Stats::tris += count/3; + } +} +void draw_model_evertex(core::Model *model, core::Entity *entity) +{ + // draw model evertices + if (model->evertex_count()) { + size_t index = model->first_evertex(); + size_t count = model->evertex_count(); - gl::push(); - gl::translate(entity->location()); - gl::rotate(entity->direction(), 0.0f, 0.0f, 1.0f ); - - if (model) { - draw_model(model, entity); - //draw_model_lights(model, entity); - } else { - if ((entity->flags() & core::Entity::Bright) == core::Entity::Bright) - gl::disable(GL_LIGHTING); - - switch(entity->shape()) { - case core::Entity::Sphere: - draw_entity_sphere(entity); - break; - - case core::Entity::Diamond: + render::gl::color(entity->color()); + glVertexPointer(3, GL_FLOAT, 0, core::VertexArray::evertex); + glNormalPointer(GL_FLOAT, 0, core::VertexArray::evertex_normal); - case core::Entity::Axis: - draw_entity_axis(entity); - break; + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); - case core::Entity::Cube: - - default: - draw_entity_cube(entity); - break; + if (r_drawwireframe && r_drawwireframe->value()) { + glDrawArrays(gl::LineLoop, index, count); + } else { + glDrawArrays(gl::Triangles, index, count); } - if ((entity->flags() & core::Entity::Bright) == core::Entity::Bright) - gl::enable(GL_LIGHTING); + Stats::tris += count/3; } - - gl::pop(); } -// draw an entity of entity_type core::Entity::Controlable -void draw_entity_controlable(core::EntityControlable *entity) +void draw_model_lights(core::Model *model, core::Entity *entity) { - core::Model *model = 0; - if (entity->modelname().size()) - model = core::Model::get(entity->modelname()); + if (model->model_light.size()) { + glPointSize(10); + gl::begin(gl::Points); - gl::push(); - gl::translate(entity->location()); - gl::rotate(entity->direction(), 0.0f, 0.0f, 1.0f ); + for (std::list::iterator lit = model->model_light.begin(); lit != model->model_light.end(); lit++) { + math::Vector3f location = (*lit)->location(); + gl::color((*lit)->color()); + gl::vertex(location); + } + + gl::end(); + glPointSize(1); + } +} - if (model ) { - draw_model(model, entity); - draw_model_engines(model, entity); - //draw_model_lights(model, entity); +void draw_model_engines(core::Model *model, core::EntityControlable *entity) +{ + if (model->model_engine.size() && entity->thrust()) { + gl::color(1.0f, 0.0f ,0.0f, 1.0f); + gl::begin(gl::Lines); + + for (std::list::iterator eit = model->model_engine.begin(); eit != model->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); + } + gl::end(); } +} + +void draw_model_radius(core::Model *model, core::Entity *entity) +{ + sphere.sphere_color = entity->color(); + sphere.sphere_color.a = 0.25f; + sphere.radius = model->radius(); + sphere.draw(); + Stats::spheres += 1; +} + +void draw_model_shield(core::Model *model, core::EntityControlable *entity) +{ // shield rotation gl::rotate(angle, 0.0f, 0.0f, 1.0f ); - gl::scale(0.2f, 0.2f, 0.2f); + gl::scale(model->radius(), model->radius(), model->radius()); // draw the shield - gl::color(math::Color(0.0f, 1.0f ,0.0f , 0.5f)); + gl::color(math::Color(0.0f, 1.0f ,0.0f)); gl::begin(gl::LineLoop); - gl::normal(0, 0.5, 0.5); +// gl::normal(0, 0.5, 0.5); gl::vertex(v1); - gl::normal(0, -0.5, 0.5); +// gl::normal(0, -0.5, 0.5); gl::vertex(v0); - gl::normal(0, -0.5, -0.5); +// gl::normal(0, -0.5, -0.5); gl::vertex(v4); - gl::normal(0, 0.5, -0.5); +// gl::normal(0, 0.5, -0.5); gl::vertex(v5); gl::end(); gl::begin(gl::LineLoop); - gl::normal(0, -0.5, 0.5); +// gl::normal(0, -0.5, 0.5); gl::vertex(v3); - gl::normal(0, 0.5, 0.5); - gl::vertex(v2); - gl::normal(0, 0.5, -0.5); +// gl::normal(0, 0.5, 0.5); + gl::vertex(v2); +// gl::normal(0, 0.5, -0.5); gl::vertex(v6); - gl::normal(0, -0.5, -0.5); +// gl::normal(0, -0.5, -0.5); gl::vertex(v7); + gl::end(); - gl::pop(); + gl::rotate(-angle, 0.0f, 0.0f, 1.0f ); } +/* ----- Render passes --------------------------------------------- */ -void draw_spacegrid(math::Vector3f const &target) + +inline bool test_draw_distance(core::Model *model, core::Entity *entity) +{ + return (model && (math::distancesquared(camera_target, entity->location()) <= (drawdistance*drawdistance*model->radius()))); +} + +inline bool test_drawfx_distance(core::Model *model, core::Entity *entity) +{ + return (model && (math::distancesquared(camera_target, entity->location()) <= (drawfxdistance*drawfxdistance*model->radius()))); +} + +/* Draw entities without model */ +void draw_pass_default() +{ + std::map::iterator it; + for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { + core::Entity *entity = (*it).second; + + if (!entity->modelname().size()) { + gl::push(); + gl::translate(entity->location()); + gl::rotate(entity->direction(), 0.0f, 0.0f, 1.0f ); + + if ((entity->flags() & core::Entity::Bright) == core::Entity::Bright) + gl::disable(GL_LIGHTING); + + switch(entity->shape()) { + case core::Entity::Sphere: + draw_entity_sphere(entity); + break; + + case core::Entity::Diamond: + + case core::Entity::Axis: + draw_entity_axis(entity); + break; + + case core::Entity::Cube: + + default: + draw_entity_cube(entity); + break; + } + + if ((entity->flags() & core::Entity::Bright) == core::Entity::Bright) + gl::enable(GL_LIGHTING); + gl::pop(); + } + } +} + +/* Draw model vertices*/ +void draw_pass_model_vertex() +{ + glVertexPointer(3, GL_FLOAT, 0, core::VertexArray::vertex); + glNormalPointer(GL_FLOAT, 0, core::VertexArray::vertex_normal); + glColorPointer(3, GL_FLOAT, 0, core::VertexArray::vertex_color); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + std::map::iterator it; + for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { + core::Entity *entity = (*it).second; + + core::Model *model = 0; + if (entity->modelname().size()) { + model = core::Model::get(entity->modelname()); + } + + if (test_draw_distance(model, entity)) { + gl::push(); + gl::translate(entity->location()); + gl::rotate(entity->direction(), 0.0f, 0.0f, 1.0f ); + + draw_model_vertex(model, entity); + + gl::pop(); + } + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); +} + +/* Draw entites with model evertices */ +void draw_pass_model_evertex() +{ + glVertexPointer(3, GL_FLOAT, 0, core::VertexArray::evertex); + glNormalPointer(GL_FLOAT, 0, core::VertexArray::evertex_normal); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + std::map::iterator it; + for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { + core::Entity *entity = (*it).second; + + core::Model *model = 0; + if (entity->modelname().size()) { + model = core::Model::get(entity->modelname()); + } + + if (test_draw_distance(model, entity)) { + gl::push(); + gl::translate(entity->location()); + gl::rotate(entity->direction(), 0.0f, 0.0f, 1.0f ); + + draw_model_evertex(model, entity); + + gl::pop(); + } + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); +} + +/* Draw model lights, engines */ +void draw_pass_model_fx() { + + for (std::map::iterator it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { + core::Entity *entity = (*it).second; + + core::Model *model = 0; + if (entity->modelname().size()) { + model = core::Model::get(entity->modelname()); + } + + if (test_drawfx_distance(model, entity) && (model->model_light.size() || (entity->type() == core::Entity::Controlable))) { + + gl::push(); + gl::translate(entity->location()); + gl::rotate(entity->direction(), 0.0f, 0.0f, 1.0f ); + + draw_model_lights(model, entity); + + if (entity->type() == core::Entity::Controlable) { + draw_model_engines(model, (core::EntityControlable *)entity); + draw_model_shield(model, (core::EntityControlable *)entity); + } + gl::pop(); + } + } +} + +void draw_pass_model_radius() +{ + if (!(r_drawradius && r_drawradius->value())) + return; + + for (std::map::iterator it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { + core::Entity *entity = (*it).second; + core::Model *model = 0; + if (entity->modelname().size()) { + model = core::Model::get(entity->modelname()); + } + + if (test_draw_distance(model, entity)) { + gl::push(); + gl::translate(entity->location()); + + draw_model_radius(model, entity); + + gl::pop(); + } + } + +} + +void draw_pass_spacegrid() { int gridsize = 32; float s = 1.0f / gridsize; float z = -4.0f; - float dx = target.x - floorf(target.x); - float dy = target.y - floorf(target.y); + float dx = camera_target.x - floorf(camera_target.x); + float dy = camera_target.y - floorf(camera_target.y); - gl::translate(target); + gl::push(); + gl::translate(camera_target); gl::color(0,0, 1.0f); gl::normal(0, 0, 1.0f); @@ -302,10 +445,16 @@ void draw_spacegrid(math::Vector3f const &target) gl::vertex(gridsize-dx, i-dy, z); } gl::end(); + + gl::pop(); } +/* ----- Main draw routine ----------------------------------------- */ + void draw(math::Vector3f const &eye, math::Vector3f const &target, float seconds) { + Stats::clear(); + // used for animations angle += 180.0f * seconds; if( angle > 360.0f ) { @@ -313,37 +462,31 @@ void draw(math::Vector3f const &eye, math::Vector3f const &target, float seconds } camera_target = target; - - // draw entities - using namespace render; gl::enable(GL_DEPTH_TEST); // enable depth buffer writing gl::enable(GL_CULL_FACE); // enable culling gl::enable(GL_COLOR_MATERIAL); // enable color tracking gl::enable(GL_LIGHTING); - gl::disable(GL_BLEND); // disbable alpha blending for world polys - std::map::iterator it; - for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { - switch ((*it).second->type()) { - case core::Entity::Default: - draw_entity_default((*it).second); - break; - case core::Entity::Controlable: - draw_entity_controlable(static_cast ((*it).second)); - break; - default: - break; - } - } + draw_pass_default(); // draw entities without model + draw_pass_model_vertex(); // draw entities with model + draw_pass_model_evertex(); // draw entities with model, vertices with entity color + + gl::disable(GL_LIGHTING); + gl::enable(GL_BLEND); + + draw_pass_model_fx(); // draw entity lights and engines + + gl::enable(GL_LIGHTING); + + draw_pass_model_radius(); //draw entity radius gl::disable(GL_LIGHTING); gl::disable(GL_COLOR_MATERIAL); // disable color tracking gl::disable(GL_CULL_FACE); // disable culling - gl::enable(GL_BLEND); // enable alpha blending again - draw_spacegrid(target); // draw the blue spacegrid + draw_pass_spacegrid(); // draw the blue spacegrid gl::disable(GL_DEPTH_TEST); // disable depth buffer writing } diff --git a/src/render/draw.h b/src/render/draw.h index 2590be2..f9f35f3 100644 --- a/src/render/draw.h +++ b/src/render/draw.h @@ -15,6 +15,14 @@ namespace render /// draw the world void draw(math::Vector3f const &eye, math::Vector3f const &target, float seconds); +class Stats { +public: + static void clear(); + + static size_t tris; + static size_t spheres; +}; + } #endif // __INCLUDED_RENDER_DRAW_H__ diff --git a/src/render/render.cc b/src/render/render.cc index b5afdf0..b7f42a8 100644 --- a/src/render/render.cc +++ b/src/render/render.cc @@ -14,6 +14,8 @@ namespace render { GLuint textures[32]; core::Cvar *r_drawradius = 0; +core::Cvar *r_drawstats = 0; +core::Cvar *r_drawwireframe = 0; void init() { @@ -35,6 +37,8 @@ void init() } r_drawradius = core::Cvar::get("r_drawradius", "0", core::Cvar::Archive); + r_drawstats = core::Cvar::get("r_drawstats", "0", core::Cvar::Archive); + r_drawwireframe = core::Cvar::get("r_drawwireframe", "0", core::Cvar::Archive); } void shutdown() diff --git a/src/render/render.h b/src/render/render.h index 7d26a3d..c622dfe 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -24,6 +24,8 @@ namespace render { extern GLuint textures[32]; extern core::Cvar *r_drawradius; + extern core::Cvar *r_drawwireframe; + extern core::Cvar *r_drawstats; } #include "render/draw.h" diff --git a/src/render/sphere.cc b/src/render/sphere.cc index 616424e..4a94acd 100644 --- a/src/render/sphere.cc +++ b/src/render/sphere.cc @@ -5,6 +5,7 @@ */ #include "render/sphere.h" +#include "render/render.h" #include "math/mathlib.h" using math::Vector3f; @@ -90,8 +91,12 @@ void Sphere::draw() for (int j=0; j < segments-1; j++) { r = radius*sintable[j]; float r1 = radius*sintable[j+1]; - - begin(QuadStrip); + // draw all vertexes + if (r_drawwireframe && r_drawwireframe->value()) { + gl::begin(gl::LineStrip); + } else { + gl::begin(gl::QuadStrip); + } v = Vector3f(r, radius*costable[j], 0); n = v; n.normalize(); -- cgit v1.2.3