/* 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 #include #include "core/application.h" #include "core/gameinterface.h" #include "core/range.h" #include "model/fragment.h" #include "model/material.h" #include "model/model.h" #include "render/render.h" #include "render/textures.h" #include "render/draw.h" #include "render/dust.h" #include "render/gl.h" #include "math/functions.h" namespace render { size_t Stats::tris = 0; size_t Stats::quads = 0; void Stats::clear() { tris = 0; quads = 0; } 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); core::Zone *zone = 0; float zone_light[4]; // locaton of the zone light math::Color zone_color; // color of the zone light bool has_zone_light = false; typedef std::map Globes; Globes globes_list; /* ---- Prepare the renderer state --------------------------------- */ void pass_prepare(float seconds) { using namespace model; // reset light state gl::disable(GL_LIGHT1); has_zone_light = false; zone_color.assign(1.0); // clear current list of globes globes_list.clear(); for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { core::Entity *entity = (*it); if (!ext_render(entity)) { new RenderExt(entity); } entity->extension((size_t) core::Extension::Render)->frame(seconds); // globes if (entity->type() == core::Entity::Globe) { core::EntityGlobe *globe = static_cast(entity); // add the globe to the globes list if (globe->visible()) { globes_list[ext_render(globe)->distance()] = globe; } // add level lights if (globe->flag_is_set(core::Entity::Bright)) { // bright globes set level light GLfloat diffuse_light[4]; GLfloat ambient_light[] = { 0.0f, 0.0f, 0.0f, 1.0f }; GLfloat specular_light[] = { 0.2f, 0.2f, 0.2f, 1.0f }; for (size_t i=0; i <3; i++) { zone_light[i] = globe->location()[i]; zone_color[i] = globe->color()[i]; diffuse_light[i] = globe->color()[i] * 0.4; } zone_light[3] = 1.0f; diffuse_light[3] = 1.0f; glLightfv(GL_LIGHT1, GL_POSITION, zone_light); glLightfv(GL_LIGHT1, GL_AMBIENT, ambient_light); glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse_light); glLightfv(GL_LIGHT1, GL_SPECULAR, specular_light); gl::enable(GL_LIGHT1); has_zone_light = true; } } } } /* ----- Skybox ---------------------------------------------------- */ void draw_sphere_inside(math::Color const & color, float radius) { gl::scale(radius, radius, radius); gl::color(color); size_t index = (model::SPHERESEGMENTS) * (model::SPHERESEGMENTS-1); size_t count = (model::SPHERESEGMENTS)*2; // draw body for (int j=0; j < (model::SPHERESEGMENTS-1)/2; j++) { glDrawArrays(gl::QuadStrip, index, count); index += count; Stats::quads += count/2-1; } } void draw_pass_sky() { if (!(r_sky && r_sky->value())) return; if (!core::localplayer()->zone()) return; if (!core::localplayer()->zone()->sky().size()) return; if (!core::localplayer()->zone()->sky_texture()) { std::string texture_name("textures/env/"); texture_name.append(core::localplayer()->zone()->sky()); core::localplayer()->zone()->set_sky_texture(Textures::load(texture_name)); if (!core::localplayer()->zone()->sky_texture()) { core::localplayer()->zone()->set_sky(""); return; } } Textures::bind(core::localplayer()->zone()->sky_texture()); gl::enable(GL_TEXTURE_2D); gl::push(); gl::translate(Camera::eye()); draw_sphere_inside(math::Color(), 1016.0f); gl::pop(); gl::disable(GL_TEXTURE_2D); } /* ---- Globes ----------------------------------------------------- */ void draw_sphere(math::Color const & color, float radius) { gl::scale(radius, radius, radius); gl::color(color); size_t index = 0; size_t count = (model::SPHERESEGMENTS)*2; // draw body for (int j=0; j < (model::SPHERESEGMENTS-1)/2; j++) { glDrawArrays(gl::QuadStrip, index, count); index += count; Stats::quads += count/2-1; } } void draw_globe(core::EntityGlobe *globe) { /* Globes have to be rendered distance sorted, closest last. Globes behind farplane are rescaled and repositioned. */ math::Vector3f location(globe->location()); float radius = globe->radius(); if(globe->flag_is_set(core::Entity::Bright)) { // bright globe, render fullbright gl::disable(GL_LIGHTING); } else { // disable camera light, level light only gl::disable(GL_LIGHT0); } if (globe->render_texture) { // textured globe Textures::bind(globe->render_texture); gl::enable(GL_TEXTURE_2D); } if (ext_render(globe)->distance() > farplane) { // globe is behind the far plane, make a fake size calculation location = Camera::eye() + (location - Camera::eye()) * (farplane / ext_render(globe)->distance()); radius *= farplane / ext_render(globe)->distance(); gl::depthmask(GL_FALSE); if (has_zone_light) { // move zone light float fake_light[4]; for (size_t i=0; i < 3; i++) { fake_light[i] = zone_light[i] + location[i] - globe->location()[i]; } fake_light[3] = 1.0f; glLightfv(GL_LIGHT1, GL_POSITION, fake_light); } } gl::push(); gl::translate(location); gl::multmatrix(globe->axis()); if (globe->rotationspeed()) { float angle = math::degrees360f(core::application()->time() * globe->rotationspeed()); gl::rotate(angle, math::Vector3f::Zaxis()); } draw_sphere(globe->color(), radius); gl::pop(); if(globe->flag_is_set(core::Entity::Bright)) { math::Vector3f v = globe->location() - Camera::eye(); v.normalize(); float a = dotproduct(v, Camera::axis().forward()); if (a > 0.1f) { // FIXME a corona is actually just a giant flare if (!globe->render_texture) { gl::enable(GL_TEXTURE_2D); } Textures::bind("textures/fx/corona"); /* if (ext_render(globe)->distance() <= farplane) { gl::depthmask(GL_FALSE); }*/ gl::disable(GL_DEPTH_TEST); math::Color color(globe->color()); color.a = a - 0.1f; gl::color(color); gl::enable(GL_BLEND); gl::begin(gl::Quads); glTexCoord2f(0,1); gl::vertex(location+ (Camera::axis().up() - Camera::axis().left()) * radius * 4.0f); glTexCoord2f(0,0); gl::vertex(location+ (Camera::axis().up() + Camera::axis().left()) * radius * 4.0f); glTexCoord2f(1,0); gl::vertex(location+ (Camera::axis().up() * -1 + Camera::axis().left()) * radius * 4.0f); glTexCoord2f(1,1); gl::vertex(location+ (Camera::axis().up() * -1 - Camera::axis().left()) * radius * 4.0f); gl::end(); Stats::quads++; gl::disable(GL_BLEND); /* if (ext_render(globe)->distance() <= farplane) { gl::depthmask(GL_TRUE); }*/ if (!globe->render_texture) { gl::disable(GL_TEXTURE_2D); } gl::enable(GL_DEPTH_TEST); } } if (ext_render(globe)->distance() > farplane) { gl::depthmask(GL_TRUE); if (has_zone_light) { // restore zone light glLightfv(GL_LIGHT1, GL_POSITION, zone_light); } } if (globe->flag_is_set(core::Entity::Bright)) { gl::enable(GL_LIGHTING); } else { gl::enable(GL_LIGHT0); } if (globe->render_texture) { gl::disable(GL_TEXTURE_2D); } } void draw_pass_globes() { // draw globes first, closest last for (Globes::reverse_iterator rit = globes_list.rbegin(); rit != globes_list.rend(); rit++) { draw_globe((*rit).second); } } /* ---- Default entities ------------------------------------------ */ void draw_entity_sphere(core::Entity *entity) { draw_sphere(entity->color(), entity->radius()); } void draw_entity_cube(core::Entity *entity) { float radius = entity->radius(); 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_diamond(core::Entity *entity) { float radius = entity->radius()/2; /* ---- draw axis lines ---- */ gl::color(entity->color_second()); gl::begin(gl::Lines); gl::vertex(1.25f * radius, 0, 0); gl::vertex(2* radius, 0, 0); gl::vertex(0, 1.25f * radius, 0); gl::vertex(0, 2* radius, 0); gl::vertex(0, 0, 1.25f * radius); gl::vertex(0, 0, 2 * radius); gl::vertex(-1.25f * radius, 0, 0); gl::vertex(-2 * radius, 0, 0); gl::vertex(0, -1.25f * radius, 0); gl::vertex(0, -2 * radius, 0); gl::vertex(0, 0, -1.25f * radius); gl::vertex(0, 0, -2 * radius); gl::end(); /* ---- draw rotating body lines ---- */ float angle = (core::application()->time() + ext_render(entity)->fuzz() ) * 45.0f; angle = angle - 360.0f * floorf(angle / 360.0f); gl::rotate(angle, math::Vector3f::Zaxis()); if (r_wireframe->value() == 0.0f) { glPolygonMode(GL_FRONT, GL_LINE); } gl::color(entity->color()); gl::begin(gl::TriangleFan ); gl::normal(0, 0 , 1); gl::vertex(0, 0, radius); gl::normal(1, 0 ,0); gl::vertex(radius, 0.0f, 0.0f); gl::normal(0, 1, 0); gl::vertex(0.0f, radius, 0.0f); gl::normal(-1, 0 ,0); gl::vertex(-radius, 0.0f, 0.0f); gl::normal(0, -1, 0); gl::vertex(0.0f, -radius, 0.0f); gl::normal(1, 0 ,0); gl::vertex(radius, 0.0f, 0.0f); gl::end(); gl::begin(gl::TriangleFan); gl::normal(0, 0 , -1); gl::vertex(0, 0, -radius); gl::normal(1, 0, 0); gl::vertex(radius, 0.0f, 0.0f); gl::normal(0, -1, 0); gl::vertex(0.0f, -radius, 0.0f); gl::normal(-1, 0 ,0); gl::vertex(-radius, 0.0f, 0.0f); gl::normal(0, 1, 0); gl::vertex(0.0f, radius, 0.0f); gl::normal(1, 0 ,0); gl::vertex(radius, 0.0f, 0.0f); gl::end(); if (r_wireframe->value() == 0.0f) { glPolygonMode(GL_FRONT, GL_FILL); } } void draw_entity_axis(core::Entity *entity) { float r = entity->radius(); gl::begin(gl::Lines); gl::color(entity->color_second()); 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(); } void draw_pass_default() { for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); ++it) { core::Entity *entity = (*it); if (!entity->serverside() && !entity->model() && (entity->type() != core::Entity::Globe)) { gl::push(); gl::translate(entity->location()); gl::multmatrix(entity->axis()); if (entity->flag_is_set(core::Entity::Bright)) { gl::disable(GL_LIGHTING); } switch(entity->shape()) { case core::Entity::Sphere: draw_entity_sphere(entity); break; case core::Entity::Diamond: draw_entity_diamond(entity); break; case core::Entity::Axis: draw_entity_axis(entity); break; case core::Entity::Cube: default: draw_entity_cube(entity); break; } if (entity->flag_is_set(core::Entity::Bright)) { gl::enable(GL_LIGHTING); } gl::pop(); } } } /* ---- Model Fragments -------------------------------------------- */ void draw_fragment(model::Fragment *fragment, bool draw_details) { size_t index = fragment->index(); size_t vertex_count = fragment->structural_size(); if (draw_details) vertex_count += fragment->detail_size(); switch (fragment->type()) { case model::Fragment::Triangles: glDrawArrays(gl::Triangles, index, vertex_count); Stats::tris += vertex_count / 3; break; case model::Fragment::Quads: glDrawArrays(gl::Quads, index, vertex_count); Stats::quads += vertex_count / 4; break; } } void draw_model_fragments(model::Model *model, const math::Color & color_primary, const math::Color & color_secondary, const bool detail = true, const bool power = true, const float thrust = 0.0f) { if (!model) return; // default material, lighted and geometry color const model::Material *material = 0; bool use_light = true; // gl::disable(GL_LIGHTING) is set //bool use_color_array = true; // glEnableClientState(GL_COLOR_ARRAY) is set for (model::Model::Groups::iterator git = model->groups().begin(); git != model->groups().end(); git++) { model::FragmentGroup *group = (*git); if (group->type() == model::FragmentGroup::Rotate) { gl::push(); gl::translate(group->location()); float rotation_angle = math::degrees360f(core::application()->time() * group->speed()); gl::rotate(-rotation_angle, group->axis().forward()); gl::translate(group->location()* -1.0f); } for (model::FragmentGroup::iterator fit = group->begin(); fit != group->end(); fit++) { model::Fragment *fragment = (*fit); if (fragment->material() != material) { material = fragment->material(); if (material) { if (material->flags() & model::Material::Engine) { /* if (use_color_array) { glDisableClientState(GL_COLOR_ARRAY); use_color_array = false; }*/ gl::color(model->enginecolor() * thrust); } else if (material->flags() & model::Material::Tertiary) { /* if (use_color_array) { use_color_array = false; glDisableClientState(GL_COLOR_ARRAY); }*/ math::Color color; if ((material->flags() & model::Material::Tertiary) == model::Material::Tertiary) { for (size_t i = 0; i < 3; i++) color[i] = (color_primary[i] + color_secondary[i]) / 2; } else if ((material->flags() & model::Material::Secondary) == model::Material::Secondary) { color.assign(color_secondary); } if ((material->flags() & model::Material::Primary) == model::Material::Primary) { color.assign(color_primary); } color.r *= material->color().r; color.g *= material->color().g; color.b *= material->color().b; gl::color(color); } else { /* if (!use_color_array) { glEnableClientState(GL_COLOR_ARRAY); use_color_array = true; }*/ gl::color(material->color()); } if (power && (material->flags() & model::Material::Bright)) { if (use_light) { gl::disable(GL_LIGHTING); use_light = false; } } else if (power && (material->flags() & model::Material::Engine)) { if (use_light) { gl::disable(GL_LIGHTING); use_light = false; } } else { if (!use_light) { gl::enable(GL_LIGHTING); use_light = true; } } } else { /// material not found if (use_light) { gl::disable(GL_LIGHTING); use_light = false; } /* if (!use_color_array) { glEnableClientState(GL_COLOR_ARRAY); use_color_array = true; }*/ gl::color(1.0f, 0.0f, 1.0f); } } draw_fragment(fragment, detail); } if (group->type() == model::FragmentGroup::Rotate) { gl::pop(); } } if (!use_light) { gl::enable(GL_LIGHTING); } /* if (!use_color_array) { glEnableClientState(GL_COLOR_ARRAY); }*/ } void draw_model_fragments(core::Entity *entity) { model::Model *model = entity->model(); if (!model) return; bool power = true; float thrust = 0.0f; if ((entity->type() == core::Entity::Dynamic) || (entity->type() == core::Entity::Controlable)) { int state = static_cast(entity)->state(); if ((state == core::Entity::NoPower) || (state == core::Entity::Destroyed)) { power = false; } else if (entity->type() == core::Entity::Controlable) { core::EntityControlable *ec = static_cast(entity); if ((ec->state() == core::Entity::Impulse) || (ec->state() == core::Entity::ImpulseInitiate)) { thrust = 1.0f; } else { thrust = ec->thrust(); } } } draw_model_fragments(model, entity->color(), entity->color_second(), ext_render(entity)->detailvisible(), power, thrust); } // draw bounding box void draw_model_bbox(model::Model *model) { // top gl::begin(gl::LineLoop); gl::vertex(model->model_maxbbox.x, model->model_maxbbox.y, model->model_maxbbox.z); gl::vertex(model->model_minbbox.x, model->model_maxbbox.y, model->model_maxbbox.z); gl::vertex(model->model_minbbox.x, model->model_minbbox.y, model->model_maxbbox.z); gl::vertex(model->model_maxbbox.x, model->model_minbbox.y, model->model_maxbbox.z); gl::end(); // bottom gl::begin(gl::LineLoop); gl::vertex(model->model_maxbbox.x, model->model_maxbbox.y, model->model_minbbox.z); gl::vertex(model->model_minbbox.x, model->model_maxbbox.y, model->model_minbbox.z); gl::vertex(model->model_minbbox.x, model->model_minbbox.y, model->model_minbbox.z); gl::vertex(model->model_maxbbox.x, model->model_minbbox.y, model->model_minbbox.z); gl::end(); gl::begin(gl::Lines); gl::vertex(model->model_maxbbox.x, model->model_maxbbox.y, model->model_maxbbox.z); gl::vertex(model->model_maxbbox.x, model->model_maxbbox.y, model->model_minbbox.z); gl::vertex(model->model_minbbox.x, model->model_maxbbox.y, model->model_maxbbox.z); gl::vertex(model->model_minbbox.x, model->model_maxbbox.y, model->model_minbbox.z); gl::vertex(model->model_minbbox.x, model->model_minbbox.y, model->model_maxbbox.z); gl::vertex(model->model_minbbox.x, model->model_minbbox.y, model->model_minbbox.z); gl::vertex(model->model_maxbbox.x, model->model_minbbox.y, model->model_maxbbox.z); gl::vertex(model->model_maxbbox.x, model->model_minbbox.y, model->model_minbbox.z); gl::end(); } void draw_pass_model_fragments() { for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { core::Entity *entity = (*it); if (entity->model() && ext_render(entity)->visible()) { gl::push(); gl::translate(entity->location()); gl::multmatrix(entity->axis()); draw_model_fragments(entity); if (r_bbox->value()) { gl::color(entity->color()); draw_model_bbox(entity->model()); } gl::pop(); } } } /* ---- Model FX --------------------------------------------------- */ void draw_pass_model_fx(float elapsed) { //const size_t count = 8; // number of engine trail particles float t = 0.0f; float a = 0.0f; float light_size = 0.0f; bool power = true; float thrust; //math::Vector3f quad[4]; math::Vector3f location; math::Vector3f offset; math::Color color; model::Light *light; model::Flare *flare; math::Axis flare_axis; for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { core::Entity *entity = (*it); power = true; if ((entity->type() == core::Entity::Controlable) || (entity->type() == core::Entity::Dynamic)) { int state = static_cast(entity)->state(); if ((state == core::Entity::NoPower) || (state == core::Entity::Destroyed)) { power = false; } } if (entity->model() && ext_render(entity)->detailvisible() && power) { // disable culling by default gl::disable(GL_CULL_FACE); model::Cull current_cull = model::CullNone; // default light texture size_t current_texture = Textures::bind("textures/fx/flare00"); gl::enable(GL_TEXTURE_2D); gl::begin(gl::Quads); // draw model lights for (model::Model::Lights::iterator lit = entity->model()->lights().begin(); lit != entity->model()->lights().end(); lit++) { light = (*lit); // strobe frequency t = 1.0f; if (light->strobe()) t = (core::application()->time() + ext_render(entity)->fuzz() - light->offset()) * light->frequency(); if ((!light->strobe()) || (( t - floorf(t)) <= light->time())) { location.assign(entity->location() + (entity->axis() * light->location())); light_size = 0.0625 * light->radius(); // track stat changes if (current_texture != light->texture()) { gl::end(); current_texture = Textures::bind(light->texture()); gl::begin(gl::Quads); } if (light->entity()) { color.assign(entity->color()); } else { color.assign(light->color()); } color.a = 0.8; gl::color(color); glTexCoord2f(0,1); gl::vertex(location + (Camera::axis().up() - Camera::axis().left()) * light_size); glTexCoord2f(0,0); gl::vertex(location + (Camera::axis().up() + Camera::axis().left()) * light_size); glTexCoord2f(1,0); gl::vertex(location + (Camera::axis().up() * -1 + Camera::axis().left()) * light_size); glTexCoord2f(1,1); gl::vertex(location + (Camera::axis().up() * -1 - Camera::axis().left()) * light_size); Stats::quads++; } } // draw flares for (model::Model::Flares::iterator flit = entity->model()->flares().begin(); flit != entity->model()->flares().end(); flit++) { flare = (*flit); // engine flares thrust = 1.0f; if (flare->engine() && ( entity->type() == core::Entity::Controlable)) { core::EntityControlable *ec = static_cast(entity); if ((ec->state() == core::Entity::ImpulseInitiate) || (ec->state() == core::Entity::Impulse)) { thrust = 1.0f; } else { thrust = ec->thrust(); } } // strobe frequency t = 1.0f; if (flare->strobe()) t = (core::application()->time() + ext_render(entity)->fuzz() - flare->offset()) * flare->frequency(); if ((thrust > 0 ) && ((!flare->strobe()) || (( t - floorf(t)) <= flare->time()))) { flare_axis.assign(entity->axis() * flare->axis()); location.assign(entity->location() + (entity->axis() * flare->location())); light_size = 0.0625 * flare->radius(); if ((current_cull != flare->cull()) || (current_texture != flare->texture())) { gl::end(); if (current_texture != flare->texture()) { current_texture = Textures::bind(flare->texture()); } if (current_cull != flare->cull()) { if (flare->cull() == model::CullNone) { gl::disable(GL_CULL_FACE); current_cull = model::CullNone; } else { if (current_cull == model::CullNone) { gl::enable(GL_CULL_FACE); } if (flare->cull() == model::CullBack) { gl::cullface(GL_BACK); current_cull = model::CullBack; } else { gl::cullface(GL_FRONT); current_cull = model::CullFront; } } } gl::begin(gl::Quads); } a = math::absf( dotproduct(flare_axis.forward(), Camera::axis().forward())); if (a > 0.1f) { a = a - 0.1f; if (flare->entity()) { color.assign(entity->color()); } else if (flare->engine()) { color.assign(entity->model()->enginecolor()); a *= thrust; } else { color.assign(flare->color()); } color.a = a; gl::color(color); glTexCoord2f(0,1); gl::vertex(location + (flare_axis.up() + flare_axis.left()) * light_size); glTexCoord2f(0,0); gl::vertex(location + (flare_axis.up() - flare_axis.left()) * light_size); glTexCoord2f(1,0); gl::vertex(location + (flare_axis.up() * -1 - flare_axis.left()) * light_size); glTexCoord2f(1,1); gl::vertex(location + (flare_axis.up() * -1 + flare_axis.left()) * light_size); Stats::quads++; } } } gl::end(); // draw particle systems if (r_particles->value() && ext_render(entity)->particles().size()) { for (RenderExt::ParticleSystems::iterator it = ext_render(entity)->particles().begin(); it != ext_render(entity)->particles().end(); it++) { ParticleSystem *particlesystem = (*it); if (current_cull != particlesystem->cull()) { if (particlesystem->cull() == model::CullNone) { gl::disable(GL_CULL_FACE); current_cull = model::CullNone; } else { if (current_cull == model::CullNone) { gl::enable(GL_CULL_FACE); } if (particlesystem->cull() == model::CullBack) { gl::cullface(GL_BACK); current_cull = model::CullBack; } else { gl::cullface(GL_FRONT); current_cull = model::CullFront; } } } particlesystem->draw(elapsed); } } } } gl::disable(GL_TEXTURE_2D); gl::cullface(GL_BACK); gl::enable(GL_CULL_FACE); } void draw_pass_model_radius() { if (!(r_radius && r_radius->value())) return; for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { core::Entity *entity = (*it); if (entity->model() && ext_render(entity)->visible()) { gl::push(); gl::translate(entity->location()); math::Color color = entity->color(); color.a = 0.25f; draw_sphere(color, entity->model()->radius()); gl::pop(); } } } void draw_pass_spacegrid() { if (!(r_grid && r_grid->value())) return; 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(float seconds) { zone = core::localplayer()->zone(); // calculate client state pass_prepare(seconds); // enable wireframe mode if requested if (r_wireframe && r_wireframe->value()) { glPolygonMode(GL_FRONT, GL_LINE); } else { glPolygonMode(GL_FRONT, GL_FILL); } // set vertex array pointers glVertexPointer(3, GL_FLOAT, 0, vertexarray->vertex()); glNormalPointer(GL_FLOAT, 0, vertexarray->normal()); glColorPointer(3, GL_FLOAT, 0, vertexarray->color()); glTexCoordPointer(3, GL_FLOAT, 0, vertexarray->texture()); // enable vertex arrays glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); // glDisableClientState(GL_COLOR_ARRAY); gl::disable(GL_DEPTH_TEST); gl::depthmask(GL_FALSE); // disable depth buffer writing draw_pass_sky(); // draw the skysphere gl::depthmask(GL_TRUE); // enable writing to the depth buffer gl::enable(GL_DEPTH_TEST); gl::enable(GL_CULL_FACE); // enable culling gl::enable(GL_COLOR_MATERIAL); // enable color tracking gl::enable(GL_LIGHTING); //gl::enable(GL_RESCALE_NORMAL); // rescale normals by the transformation matrix scale factor gl::enable(GL_NORMALIZE); draw_pass_globes(); // draw globes draw_pass_default(); // draw entities without model gl::disable(GL_NORMALIZE); //gl::disable(GL_RESCALE_NORMAL); // glEnableClientState(GL_COLOR_ARRAY); draw_pass_model_fragments(); // glDisableClientState(GL_COLOR_ARRAY); gl::disable(GL_LIGHTING); gl::enable(GL_BLEND); gl::depthmask(GL_FALSE); // disable depth buffer writing draw_pass_spacegrid(); // draw the blue spacegrid if (!core::localplayer()->view()) { Dust::draw(zone_color); // draw spacedust } draw_pass_model_fx(seconds); // draw entity lights and engines gl::enable(GL_LIGHTING); gl::enable(GL_RESCALE_NORMAL); draw_pass_model_radius(); // draw entity radius glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); gl::disable(GL_RESCALE_NORMAL); gl::disable(GL_LIGHTING); gl::disable(GL_COLOR_MATERIAL); // disable color tracking gl::disable(GL_CULL_FACE); // disable culling gl::depthmask(GL_TRUE); // enable depth buffer writing gl::disable(GL_DEPTH_TEST); // disable depth buffer testing // GL_BLEND must be enabled for the GUI } void draw_target(core::Entity *entity) { model::Model *model = entity->model(); if (!model) return; if (!model->docks().size()) return; float d = math::distance(core::localcontrol()->location(), entity->location()) - entity->radius() - core::localcontrol()->radius(); if (d > 100.0f) return; gl::enable(GL_DEPTH_TEST); gl::push(); gl::translate(entity->location()); gl::multmatrix(entity->axis()); gl::color(0, 1.0f, 1.0f, 1.0f); for (model::Model::Docks::iterator dit = model->docks().begin(); dit != model->docks().end(); dit++) { model::Dock *dock = (*dit); math::Vector3f maxbox(dock->location()); math::Vector3f minbox(dock->location()); for (size_t i=0; i < 3; i++) { maxbox[i] += 0.025; minbox[i] -= 0.025; } // top gl::begin(gl::LineLoop); gl::vertex(maxbox.x, maxbox.y, maxbox.z); gl::vertex(minbox.x, maxbox.y, maxbox.z); gl::vertex(minbox.x, minbox.y, maxbox.z); gl::vertex(maxbox.x, minbox.y, maxbox.z); gl::end(); // bottom gl::begin(gl::LineLoop); gl::vertex(maxbox.x, maxbox.y, minbox.z); gl::vertex(minbox.x, maxbox.y, minbox.z); gl::vertex(minbox.x, minbox.y, minbox.z); gl::vertex(maxbox.x, minbox.y, minbox.z); gl::end(); gl::begin(gl::Lines); gl::vertex(maxbox.x, maxbox.y, maxbox.z); gl::vertex(maxbox.x, maxbox.y, minbox.z); gl::vertex(minbox.x, maxbox.y, maxbox.z); gl::vertex(minbox.x, maxbox.y, minbox.z); gl::vertex(minbox.x, minbox.y, maxbox.z); gl::vertex(minbox.x, minbox.y, minbox.z); gl::vertex(maxbox.x, minbox.y, maxbox.z); gl::vertex(maxbox.x, minbox.y, minbox.z); gl::end(); } gl::pop(); gl::disable(GL_DEPTH_TEST); } }