diff options
author | Stijn Buys <ingar@osirion.org> | 2008-08-02 18:53:57 +0000 |
---|---|---|
committer | Stijn Buys <ingar@osirion.org> | 2008-08-02 18:53:57 +0000 |
commit | 38bfca98a4203130251b4848d1f4c0f0c3c28ff4 (patch) | |
tree | c0ecc741440906b89d2a802dfc684538a566d9d7 /src/render | |
parent | 417485ca452b95b591af5fb639bf9bbb793e9912 (diff) |
improved globe rendering
Diffstat (limited to 'src/render')
-rw-r--r-- | src/render/draw.cc | 597 |
1 files changed, 324 insertions, 273 deletions
diff --git a/src/render/draw.cc b/src/render/draw.cc index d440706..3e3a13e 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -41,22 +41,158 @@ math::Vector3f v7(-1, -1, -1); const float drawdistance = 128.0f; const float drawfxdistance = 64.0f; +const float farplane = 1016.0f; + core::Zone *zone = 0; +float zone_light[4]; +bool has_zone_light = false; + +typedef std::map<float, core::EntityGlobe *> Globes; +Globes globes_list; + // function to test flags inline bool flag_is_set(unsigned int const spawnflags, unsigned int const flag) { return ((spawnflags & flag) == flag); } -/* ----- Default Entity shapes ------------------------------------- */ +/* ---- Prepare the renderer state --------------------------------- */ -void draw_sphere(math::Color const & color, float radius) +void pass_prepare(float seconds) +{ + using namespace model; + + // reset light state + gl::disable(GL_LIGHT1); + has_zone_light = false; + + // 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); + + // load entity models and light flare textures + if (!entity->model() && entity->modelname().size()) { + entity->entity_model = Model::load(entity->modelname()); + + if (!entity->model()) { + entity->entity_modelname.clear(); + entity->entity_radius = 0.25; + } else { + // set entity radius to model radius + entity->entity_radius = entity->entity_model->radius(); + + for (Model::Lights::iterator lit = entity->model()->lights().begin(); lit != entity->model()->lights().end(); lit++) { + Light *light = (*lit); + + // load light texture + std::stringstream flarename; + flarename << "bitmaps/fx/flare" << std::setfill('0') << std::setw(2) << light->flare(); + light->render_texture = Textures::load(flarename.str()); + } + + for(Model::Engines::iterator eit = entity->model()->engines().begin(); eit != entity->model()->engines().end(); eit++) { + Engine *engine = (*eit); + + if (!engine->flare()) engine->engine_flare = 1; + + // load engine texture + std::stringstream flarename; + flarename << "bitmaps/fx/flare" << std::setfill('0') << std::setw(2) << engine->flare(); + engine->render_texture = Textures::load(flarename.str()); + } + + for (Model::Flares::iterator flit = entity->model()->flares().begin(); flit != entity->model()->flares().end(); flit++) { + Flare *flare = (*flit); + + // load flare texture + std::stringstream flarename; + flarename << "bitmaps/fx/flare" << std::setfill('0') << std::setw(2) << flare->flare(); + flare->render_texture = Textures::load(flarename.str()); + } + } + } + + if (!entity->state()) { + entity->entity_clientstate = new core::ClientState(entity); + } + + entity->state()->state_visible = false; + entity->state()->state_detailvisible = false; + entity->state()->state_targetable = false; + + entity->state()->state_distance = math::distance(Camera::eye(), entity->state()->location()); + + // calculate visibility for entities with models + if (entity->model()) { + + float r = entity->model()->radius(); + math::clamp(r, 1.0f, 5.0f); + if (entity->state()->distance() < drawfxdistance * r) { + // entites within detail range + entity->state()->state_visible = true; + entity->state()->state_detailvisible = true; + } else if (entity->state()->distance() < drawdistance * r) { + // entities within drawing distance, outside detail range + entity->state()->state_visible = true; + entity->state()->state_detailvisible = false; + } + + } else { + entity->state()->state_visible = true; + + if (entity->type() == core::Entity::Globe) { + + core::EntityGlobe *globe = static_cast<core::EntityGlobe *>(entity); + // add the globe to the globes list + + globes_list[globe->state()->distance()] = globe; + + if (flag_is_set(globe->flags(), 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]; + 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; + } else { + + // load globe textures + if (!globe->render_texture && globe->texture().size()) { + std::stringstream texname; + texname << "textures/" << globe->texture(); + globe->render_texture = Textures::load(texname.str()); + if (!globe->render_texture) + globe->entity_texture.clear(); + } + } + } + } + } +} + +/* ----- Skybox ---------------------------------------------------- */ + +void draw_sphere_inside(math::Color const & color, float radius) { - //gl::push(); gl::scale(radius, radius, radius); gl::color(color); - size_t index = 0; + size_t index = (model::SPHERESEGMENTS) * (model::SPHERESEGMENTS-1); size_t count = (model::SPHERESEGMENTS)*2; // draw body @@ -66,16 +202,46 @@ void draw_sphere(math::Color const & color, float radius) Stats::quads += count/2-1; } - //gl::pop(); } -void draw_sphere_inside(math::Color const & color, float radius) +void draw_pass_sky() +{ + if (!(r_sky && r_sky->value())) + return; + + if (!core::localplayer()->zone()) + return; + + if (!core::localplayer()->zone()->sky_texture() && core::localplayer()->zone()->sky().size()) { + + 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(""); + } + + 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::push(); gl::scale(radius, radius, radius); gl::color(color); - size_t index = (model::SPHERESEGMENTS) * (model::SPHERESEGMENTS-1); + size_t index = 0; size_t count = (model::SPHERESEGMENTS)*2; // draw body @@ -84,36 +250,96 @@ void draw_sphere_inside(math::Color const & color, float radius) index += count; Stats::quads += count/2-1; } - - //gl::pop(); } -void draw_entity_sphere(core::Entity *entity) +void draw_globe(core::EntityGlobe *globe) { - if ((entity->type() == core::Entity::Globe) && !flag_is_set(entity->flags(), core::Entity::Bright)) { - gl::disable(GL_LIGHT0); // disable camera light, level light only - - core::EntityGlobe *globe = (core::EntityGlobe *)entity; - if (globe->render_texture) { - Textures::bind(globe->render_texture); - gl::enable(GL_TEXTURE_2D); + /* + Globes have to be rendered distance sorted, closest last. + Globes behind farplane should be rendered with z-buffer writes disabled. + */ + math::Vector3f location(globe->state()->location()); + float radius = globe->radius(); + + if(flag_is_set(globe->flags(), 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 (globe->state()->distance() > farplane) { + // globe is behind the far plane, make a fake size calculation + location = Camera::eye() + (location - Camera::eye()) * (farplane / globe->state()->distance()); + radius *= farplane / globe->state()->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->state()->location()[i]; + } + fake_light[3] = 1.0f; + glLightfv(GL_LIGHT1, GL_POSITION, fake_light); } } - draw_sphere(entity->color(), entity->radius()); + gl::push(); + gl::translate(location); + gl::multmatrix(globe->state()->axis()); + + draw_sphere(globe->color(), radius); + gl::pop(); + + if (globe->state()->distance() > farplane) { - if ((entity->type() == core::Entity::Globe) && !flag_is_set(entity->flags(), core::Entity::Bright)) { - core::EntityGlobe *globe = (core::EntityGlobe *)entity; - if (globe->render_texture) { - gl::disable(GL_TEXTURE_2D); + gl::depthmask(GL_TRUE); + + if (has_zone_light) { + // restore zone light + glLightfv(GL_LIGHT1, GL_POSITION, zone_light); } + } + + if (flag_is_set(globe->flags(), 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()); @@ -230,8 +456,8 @@ void draw_entity_diamond(core::Entity *entity) 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); @@ -243,10 +469,46 @@ void draw_entity_axis(core::Entity *entity) gl::vertex(0.0f,0.0f,r); gl::vertex(0.0f,0.0f,-r); - gl::end(); + gl::end(); } -/* ----- model fragments ------------------------------------------- */ +void draw_pass_default() +{ + for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); ++it) { + + core::Entity *entity = (*it); + if (!entity->model() && (entity->type() != core::Entity::Globe)) { + + gl::push(); + gl::translate(entity->state()->location()); + gl::multmatrix(entity->state()->axis()); + + 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; + } + + gl::pop(); + } + } +} + +/* ---- Model Fragments -------------------------------------------- */ void draw_fragment(model::Fragment *fragment, bool draw_details) { @@ -365,225 +627,37 @@ void draw_model_fragments(core::Entity *entity) } } - -/* ----- Render passes --------------------------------------------- */ - -/* calculate entity visibility */ -void pass_prepare(float seconds) +// draw bounding box +void draw_model_bbox(model::Model *model) { - using namespace model; - - // reset light state - gl::disable(GL_LIGHT1); - - // get the current OpenGL transformation matrices - GLdouble gl_projection_matrix[16]; - GLdouble gl_model_matrix[16]; - GLint gl_viewport[4]; - - glGetDoublev(GL_PROJECTION, gl_projection_matrix); - glGetDoublev(GL_MODELVIEW, gl_model_matrix); - glGetIntegerv(GL_VIEWPORT, gl_viewport); - - for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { - core::Entity *entity = (*it); - - // load entity models and light flare textures - if (!entity->model() && entity->modelname().size()) { - entity->entity_model = Model::load(entity->modelname()); - - if (!entity->model()) { - entity->entity_modelname.clear(); - entity->entity_radius = 0.25; - } else { - // set entity radius to model radius - entity->entity_radius = entity->entity_model->radius(); - - for (Model::Lights::iterator lit = entity->model()->lights().begin(); lit != entity->model()->lights().end(); lit++) { - Light *light = (*lit); - - // load light texture - std::stringstream flarename; - flarename << "bitmaps/fx/flare" << std::setfill('0') << std::setw(2) << light->flare(); - light->render_texture = Textures::load(flarename.str()); - } - - for(Model::Engines::iterator eit = entity->model()->engines().begin(); eit != entity->model()->engines().end(); eit++) { - Engine *engine = (*eit); - - if (!engine->flare()) engine->engine_flare = 1; - - // load engine texture - std::stringstream flarename; - flarename << "bitmaps/fx/flare" << std::setfill('0') << std::setw(2) << engine->flare(); - engine->render_texture = Textures::load(flarename.str()); - } - - for (Model::Flares::iterator flit = entity->model()->flares().begin(); flit != entity->model()->flares().end(); flit++) { - Flare *flare = (*flit); - - // load flare texture - std::stringstream flarename; - flarename << "bitmaps/fx/flare" << std::setfill('0') << std::setw(2) << flare->flare(); - flare->render_texture = Textures::load(flarename.str()); - } - } - } - - if (!entity->state()) { - entity->entity_clientstate = new core::ClientState(entity); - } - - entity->state()->state_visible = false; - entity->state()->state_detailvisible = false; - entity->state()->state_targetable = false; - - // calculate visibility for entities with models - if (entity->model()) { - - entity->state()->state_visible = false; - float dq = math::distancesquared(Camera::eye(), entity->location()); - - if (dq <= drawfxdistance*drawfxdistance*entity->model()->radius()) { - // entites within drawing distance - entity->state()->state_visible = true; - entity->state()->state_detailvisible = true; - } else if (dq <= drawdistance*drawdistance*entity->model()->radius()) { - // entities within drawdistance - entity->state()->state_visible = true; - entity->state()->state_detailvisible = false; - } - - } else { - entity->state()->state_visible = true; - - if (entity->type() == core::Entity::Globe) { - - core::EntityGlobe *globe = static_cast<core::EntityGlobe *>(entity); - - if (flag_is_set(globe->flags(), core::Entity::Bright)) { - - // bright globes set level light - GLfloat light_position[4]; - 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++) { - light_position[i] = globe->location()[i]; - diffuse_light[i] = globe->color()[i] * 0.4; - } - light_position[3] = 1.0f; - diffuse_light[3] = 1.0f; - - glLightfv(GL_LIGHT1, GL_POSITION, light_position); - 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); - } else { - - // load globe textures - if (!globe->render_texture && globe->texture().size()) { - std::stringstream texname; - texname << "textures/" << globe->texture(); - globe->render_texture = Textures::load(texname.str()); - if (!globe->render_texture) - globe->entity_texture.clear(); - } - } - } - } - } -} - -/* Draw entities without model */ -void draw_pass_default() -{ - for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { - core::Entity *entity = (*it); - - // draw entities without model - if (!entity->model()) { - gl::push(); - gl::translate(entity->state()->location()); - gl::multmatrix(entity->state()->axis()); - - if (flag_is_set(entity->flags(), 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 (flag_is_set(entity->flags(), core::Entity::Bright)) { - gl::enable(GL_LIGHTING); - } - - gl::pop(); - - } else if (r_bbox->value()) { - - // draw bounding box if requested - model::Model *model = entity->model(); - gl::color(entity->color()); + // 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(); - gl::push(); - gl::translate(entity->state()->location()); - gl::multmatrix(entity->state()->axis()); - - // 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(); + // 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::pop(); - - } - } + 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(); } -/* draw model geometry fragments */ void draw_pass_model_fragments() { for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it++) { @@ -596,12 +670,18 @@ void draw_pass_model_fragments() draw_model_fragments(entity); + if (r_bbox->value()) { + gl::color(entity->color()); + draw_model_bbox(entity->model()); + } + gl::pop(); } } } -/* draw model lights and engines */ +/* ---- Model FX --------------------------------------------------- */ + void draw_pass_model_fx(float elapsed) { const size_t count = 8; // number of engine trail particles @@ -822,6 +902,7 @@ void draw_pass_model_fx(float elapsed) gl::disable(GL_TEXTURE_2D); } + void draw_pass_model_corona() { if (!(r_radius && r_radius->value())) @@ -842,37 +923,6 @@ void draw_pass_model_corona() } - -/* Draw skysphere */ -void draw_pass_sky() -{ - if (!(r_sky && r_sky->value())) - return; - - if (!core::localplayer()->zone()) - return; - - if (!core::localplayer()->zone()->sky_texture() && core::localplayer()->zone()->sky().size()) { - - 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(""); - } - - 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); -} - void draw_pass_spacegrid() { if (!(r_grid && r_grid->value())) @@ -952,7 +1002,6 @@ void draw(float seconds) draw_pass_sky(); // draw the skysphere - gl::depthmask(GL_TRUE); // enable writing to the depth buffer gl::enable(GL_CULL_FACE); // enable culling @@ -961,6 +1010,8 @@ void draw(float seconds) //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); |