/* 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 { 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; 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); } } void draw_entity_sphere(core::Entity *entity) { sphere.sphere_color = entity->color(); sphere.radius = entity->radius(); sphere.draw(); } 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(); } // draw an entity of entity_type core::Entity::Default void draw_entity_default(core::Entity *entity) { using namespace render; core::Model *model = 0; if (entity->modelname().size()) { model = core::Model::get(entity->modelname()); } if (model && math::distancesquared(camera_target, entity->location()) > drawdistance*drawdistance*model->radius()) return; 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: 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 an entity of entity_type core::Entity::Controlable void draw_entity_controlable(core::EntityControlable *entity) { core::Model *model = 0; if (entity->modelname().size()) model = core::Model::get(entity->modelname()); gl::push(); gl::translate(entity->location()); gl::rotate(entity->direction(), 0.0f, 0.0f, 1.0f ); if (model ) { draw_model(model, entity); draw_model_engines(model, entity); //draw_model_lights(model, entity); } // shield rotation gl::rotate(angle, 0.0f, 0.0f, 1.0f ); gl::scale(0.2f, 0.2f, 0.2f); // draw the shield gl::color(math::Color(0.0f, 1.0f ,0.0f , 0.5f)); 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::pop(); } void draw_spacegrid(math::Vector3f const &target) { 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); gl::translate(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(); } void draw(math::Vector3f const &eye, math::Vector3f const &target, float seconds) { // used for animations angle += 180.0f * seconds; if( angle > 360.0f ) { angle -= 360.0f; } 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; } } 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 gl::disable(GL_DEPTH_TEST); // disable depth buffer writing } }