/* render/draw.cc This file is part of the Osirion project and is distributed under the terms and conditions of the GNU General Public License version 2 */ #include "core/core.h" #include "core/model.h" #include "render/render.h" #include "render/draw.h" #include "render/sphere.h" 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); math::Vector3f v1(1, 1, 1); math::Vector3f v2(-1, 1, 1); math::Vector3f v3(-1, -1, 1); math::Vector3f v4(1, -1, -1); math::Vector3f v5(1, 1, -1); 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; /* ----- 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) { float radius = entity->radius()/2; gl::scale(radius, radius, radius); gl::color(entity->color()); gl::begin(gl::Quads); // top gl::normal(0,0,1); gl::vertex(v0); gl::vertex(v1); gl::vertex(v2); gl::vertex(v3); // bottom gl::normal(0,0, -1); gl::vertex(v7); gl::vertex(v6); gl::vertex(v5); gl::vertex(v4); // sides gl::normal(1,0,0); gl::vertex(v1); gl::vertex(v0); gl::vertex(v4); gl::vertex(v5); gl::normal(-1,0,0); gl::vertex(v3); gl::vertex(v2); gl::vertex(v6); gl::vertex(v7); gl::normal(0,1,0); gl::vertex(v2); gl::vertex(v1); gl::vertex(v5); gl::vertex(v6); gl::normal(0,-1,0); gl::vertex(v0); gl::vertex(v3); gl::vertex(v7); gl::vertex(v4); gl::end(); } void draw_entity_axis(core::Entity *entity) { using namespace render; float r = entity->radius(); gl::begin(gl::Lines); gl::color(1.0f, 0.0f, 0.0f); gl::vertex(r,0.0f,0.0f); gl::color(entity->color()); gl::vertex(-r,0.0f,0.0f); gl::vertex(0.0f,r/2,0.0f); gl::vertex(0.0f,-r/2,0.0f); gl::vertex(0.0f,0.0f,r); gl::vertex(0.0f,0.0f,-r); gl::end(); } /* ----- Entity models --------------------------------------------- */ void draw_model_vertex(core::Model *model, core::Entity *entity) { // draw model vertices if (model->vertex_count()) { size_t index = model->first_vertex(); size_t count = model->vertex_count(); if (r_drawwireframe && r_drawwireframe->value()) { glDrawArrays(gl::LineLoop, index, count); } else { glDrawArrays(gl::Triangles, index, count); } 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(); render::gl::color(entity->color()); glVertexPointer(3, GL_FLOAT, 0, core::VertexArray::evertex); glNormalPointer(GL_FLOAT, 0, core::VertexArray::evertex_normal); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); if (r_drawwireframe && r_drawwireframe->value()) { glDrawArrays(gl::LineLoop, index, count); } else { glDrawArrays(gl::Triangles, index, count); } Stats::tris += count/3; } } void draw_model_lights(core::Model *model, core::Entity *entity) { if (model->model_light.size()) { 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); } } 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(model->radius(), model->radius(), model->radius()); // draw the shield gl::color(math::Color(0.0f, 1.0f ,0.0f)); gl::begin(gl::LineLoop); // gl::normal(0, 0.5, 0.5); gl::vertex(v1); // gl::normal(0, -0.5, 0.5); gl::vertex(v0); // gl::normal(0, -0.5, -0.5); gl::vertex(v4); // gl::normal(0, 0.5, -0.5); gl::vertex(v5); gl::end(); gl::begin(gl::LineLoop); // 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::vertex(v6); // gl::normal(0, -0.5, -0.5); gl::vertex(v7); gl::end(); gl::rotate(-angle, 0.0f, 0.0f, 1.0f ); } /* ----- Render passes --------------------------------------------- */ 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 = camera_target.x - floorf(camera_target.x); float dy = camera_target.y - floorf(camera_target.y); gl::push(); gl::translate(camera_target); gl::color(0,0, 1.0f); gl::normal(0, 0, 1.0f); gl::begin(gl::Lines); for (int i=-gridsize; i <= gridsize; i++) { gl::color(0,0, 0, 0); gl::vertex(i-dx, -gridsize-dy, z); gl::color(0,0, (gridsize-abs(i))*s, (gridsize-abs(i))*s); gl::vertex(i-dx, -dy, z ); gl::vertex(i-dx, -dy ,z ); gl::color(0,0, 0, 0); gl::vertex(i-dx, gridsize-dy, z); gl::vertex(-gridsize-dx, i-dy, z ); gl::color(0,0, (gridsize-abs(i))*s, (gridsize-abs(i))*s); gl::vertex(-dx, i-dy, z); gl::vertex(-dx, i-dy, z); gl::color(0,0, 0, 0); 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 ) { angle -= 360.0f; } camera_target = target; 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 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 draw_pass_spacegrid(); // draw the blue spacegrid gl::disable(GL_DEPTH_TEST); // disable depth buffer writing } }